![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Полтергейсты SQL Server или всё "намана"? [D7, MSSQL]
31512 © (2004-03-26 09:10:00)Дело было так ... Моя мечта попробовать создать трёхуровневое приложение для базы данных (SQL Server 2000), с некоторых пор начала обретать физическую форму. Для создания самоей БД на сервере я сначала использовал Access. Ну, чего проще? Сляпал БД, вызвыл "Мастер преобразования в формат SQL Server" и ... собственно больше ничего не требуется. Но потом мне надоело каждый раз лезть в Access, когда возникала необходимость создать БД заново. Тогда я написал SQL-скрипт, как говорится, "в раз и навсегда", внося по мере необходимости в него ихменения. А заставить SQL серевер выполнить SQL-скрипт не так уж сложно, да и быстрее это раз в 30.
Но вот какая фигня стала происходить. В случае создания БД Accessом, достаточно было выставить нужные флаги у DataSetProviderов для серверного приложения, чтобы в клиентском приложении при вызове метода TClientDataSet.ApplyUpdates(ErrorCount : integer) все изменения аккуратно принимались, в том числе происходили и корректные изменения в самой БД. При этом никаких дополнительных действий принимать не требуется, т.е. используются самые стандартные возможности DBшных компонентов. Однако, если БД создана посредством скипта, то ничего подобного не наблюдается. Вставить новую запись - без проблем, но на удаление и изменение получаю ошибку "Запись была изменена или занята другим пользователем" сообщением "Не удалось найти запись". И только создание бизнес-правила в методе TRemoteDataModule.DataSetProviderBeforeUpdateRecord
позволяет выполнять всё корректно. Почему же возникают, как говорят в Одессе, такие "две большие разницы"?
У меня: D7, SQL Server 2000, WinXP SP1 RUS, Office XP(with FrontPage), ADO (MDAC 2.7), MIDAS.
31512 (2004-04-07 10:27:00) [1]Вот ещё одно из возможных решений. При этом от identity отказываемся и ключевые поля имеют просто тип int...
.
.
.
var
.....
ID : integer = 0;
.....
.
.
.
procedure TForm1.ClientDataSet1NewRecord(DataSet: TDataSet);
begin
DataSet.Fields[0].AsInteger := ID;
end;
procedure TForm1.ClientDataSet1BeforeInsert(DataSet: TDataSet);
begin
ID := DataSet.Fields[0].AsInteger;
Inc(ID);
end;
31512 (2004-04-01 17:29:00) [2]Ищу у способ обойтись без внесения полей в ClientDataSet в клиентском приложении и без установления ReadOnly := False для ключевого поля.
31512 (2004-04-01 16:53:00) [3]Разумеется для теста. Вот только плох этот способ. В клиентском приложении появляется логика базы данных. Приходится в ClientDataSetе добавлять поля в редакторе + для ID_ORGANISATION устанавливать ReadOnly := False. А это не есть гуд.
Nikolay M. (2004-04-01 16:36:00) [4]
> DataSet['ID_ORGANISATION'] := Random(32768);
Надеюсь, это только для теста?
31512 (2004-04-01 16:07:00) [5]procedure TForm1.ClientDataSet1NewRecord(DataSet: TDataSet);
begin
if DataSet['ID_ORGANISATION'] = NULL then
begin
Beep;
DataSet['ID_ORGANISATION'] := Random(32768);
end;
end;
31512 (2004-04-01 16:06:00) [6]Ага. Спасибо большое. Работает вроде :)
Nikolay M. (2004-04-01 15:50:00) [7]Вот только не надо генерить ID на клиенте!
Ты в [34] ссылку читал?
31512 (2004-04-01 15:29:00) [8]Вот что написано в Helpе
TAutoIncField is a persistent field object for an autoincrement field in a dataset.
Unit
DB
Description
TAutoIncField provides access to an autoincrement field in a table. Autoincrement fields can hold values in the range -2,147,483,648 to 2,147,483,647, and are used as a counter for the records in the dataset. Each record is given a unique value in an autoincrement field, with each record receiving the next highest integer from that of the previously inserted record. Autoincrement fields are commonly used to provide a unique primary key value for a record.
Note: Auto-incrementing fields are a function of the database back-end. An application should not attempt to set a field value for an autoincrement field (with or without a TAutoIncField object).
If you use the Fields editor at design time to create a persistent field component for the auto-incrementing field, you can access it by name at runtime. When using dynamic field components, you can access the TAutoIncField instance using the dataset’s Fields property or FieldByName method.
31512 (2004-04-01 15:25:00) [9]Табличек нет - есть CliendDataSet. Поля передаются с серверного приложения, причём тип поля TAutoIncField. Т.е. суть поля определяется корректно. Почему оно не работает как TAutoIncField - этого я понять не могу.
LittleSpo (2004-04-01 14:37:00) [10]ты лутьше таблички еще раз посмотри ,
точно там есть увсех табличек куды вставляешь запись первичные ключи
31512 (2004-04-01 13:58:00) [11]Следующий код издаёт звук, когда пытаешься вставить вторую подряд запись
procedure TForm1.ClientDataSet1BeforeInsert(DataSet: TDataSet);
begin
if DataSet['ID_ORGANISATION'] = NULL then
begin
Beep;
end;
31512 (2004-04-01 12:40:00) [12]Ошибка возникает на клиенте. Источник данных - ClientDataSet. Вот если бы ошибка возникала при вызове. ClientDataSet.ApplyUpdates, тогда другой разговор. С клиетом разбираться надо. А не хотелось бы. Ошибка возникает только в том случае, если на сервере в ADOQuery добавлять поля. Если не добавлять, то приходится программно устанавливать флаги. Не желательно отказываться от постоянного списка полей на сервере.
Nikolay M. (2004-04-01 12:25:00) [13]
> Как бы обойти это...
Делай на сервере метод GenNewID, получай новую ID-шку, и присваивай ее ключевому полю в CDS.OnNewRecord.
http://rsdn.ru/article/db/midas_migration.xml#XSLTSECTION124143120120
> Для пользоваетля не нужно ключевые поля показвывать...
Ну и не показывай. Не мешай мух с котлетами.
31512 (2004-04-01 12:16:00) [14]Как бы обойти это... Для пользоваетля не нужно ключевые поля показвывать...
Nikolay M. (2004-04-01 11:59:00) [15]
> Тут дублирование ключа происходит...
Угу. Потому что после первого инсерта оно у тебя не определено.
31512 (2004-04-01 11:52:00) [16]Если так он редактирует всегда оду и ту же строку - первую.
Тут дублирование ключа происходит...
Nikolay M. (2004-04-01 11:46:00) [17]Набор Данных
31512 (2004-04-01 11:05:00) [18]Торможу. НД - это что?
Nikolay M. (2004-04-01 10:42:00) [19]Подозреваю, что если между вставками записей вставить переоткрытие НД, то все будет ок (это не решение, конечно, а только направлению к походу мысли).
31512 (2004-04-01 10:31:00) [20]!www.rsdn.ru! Полезные статьи!
*****************************************************************
Вот такая у меня фигня приключилась.
Я всё настроил. И всё работало. До тех пор, пока на серверном приложении, в RDM модуле я не внёс поля в ADOQuery с целью установления флагов. Теперь на клиентском приложении, в DBGride при попытке внести сразу две записи подряд, получаю сообщение "Key violation". Обойти это мне удалось, покамест, только явным установлением значения певичного ключа в DBGrid, ручками.
Вообще-то для пользователя нужно скрыть поле первичного ключа, незачем ему знать о его существовании.
Кстати, одна запись вносится успешно, без указания нового значения первичного ключа.
****************************************************************