DataSnap и поле autoinc

Я хотел бы, чтобы в моей таблице было поле autoinc, но вставка в него с использованием ClientDataSet вызывает ошибку «поле должно иметь значение». Кажется, что сервер Datasnap не знает, что он должен генерировать его сам, и ожидает значение. Для демонстрации я создал простую таблицу всего с двумя полями: ID (autoinc) и DATE (varchar). База данных - SQLite.

procedure TForm3.Button1Click(Sender: TObject);
begin
ClientDataSet1.Insert;
ClientDataSet1.FieldByName('DATE').Value:= DateUtils.DateOf(PlannerCalendar1.Date);
ClientDataSet1.Post;
ClientDataSet1.ApplyUpdates(0);
if ClientDataSet1.ApplyUpdates(0) = 0 then
ClientDataSet1.Refresh;

Чтобы решить проблему autoinc, я использовал предложение доктора Боба:

procedure TForm3.ClientDataSet1NewRecord(DataSet: TDataSet);
const {$J+}
ID: Integer = -1;
begin
DataSet.FieldByName('ID').AsInteger := ID;
DEC(ID) ;
end;

Хотя счетчик autoinc идет назад, я могу с этим смириться. Но... Записи добавляются в сетку, но не в базу данных!?

Так может кто-нибудь, пожалуйста, просветите меня, как справиться с этим кошмаром autoinc? Видел некоторые предложения по использованию события onreconcile набора данных, но исправление ошибки вручную не для меня. Я попытался вставить нулевое значение для поля идентификатора, надеясь, что сервер datasnap исправит ошибку, но все, что он делает, это показывает мне диалоговое окно согласования, чтобы я мог исправить проблему. Помощь !

конец;


person user3927897    schedule 11.08.2014    source источник
comment
Я считаю, что проще всего получить сгенерированный идентификатор с сервера для предоставления в сообщении. Например, см. для firebird.   -  person Sertac Akyuz    schedule 12.08.2014
comment
Оригинальная статья, я думаю, вы поняли эту идею. Если я правильно помню, я тоже не мог понять. Также см..   -  person Sertac Akyuz    schedule 12.08.2014
comment
Самое смешное, что если убрать поле autoinc, то все работает как надо. Проблема возникает, когда я пытаюсь удалить значение. Я могу удалить в сетке, но не в базе данных.   -  person user3927897    schedule 12.08.2014


Ответы (1)


Вы не говорите, какой набор данных вы используете для подключения вашего DataSetProvider к базе данных Sqlite. Я предполагаю, что это не набор данных FireDac, потому что они правильно обрабатывают столбцы autoinc в таблицах Sqlite.

Итак, предполагая, что вы используете какой-то другой тип, я думаю, вы, возможно, упустили из виду значение раздела Ошибки в

http://edn.embarcadero.com/article/20847

статья, которая была упомянута в комментариях, где говорится:

«Для СУБД, которые не сопоставляют свои поля автоинкремента с TAutoIncField, вам необходимо удалить флаг TField.ProviderFlags.pfInUpdate в исходном наборе данных, чтобы позволить DataSnap разрешить запись обратно в базу данных. Вы действительно делаете то же самое. что DataSnap делает автоматически для TAutoIncFields, делая это».

Это относится к Sqlite. Кроме того, вам нужно проверить тип столбца вашего исходного набора данных (я имею в виду тот, который питает ваш DataSetProvider) во время выполнения, если поля вашего исходного набора данных не являются постоянными.

Для Sqlite тип поля исходного набора данных должен быть ftLargeInt, а не ftAutoInc, поскольку размер столбца autoinc в базе данных Sqlite — 64-разрядный, а не 32-разрядный (как предполагает ftAutoinc). Самый простой способ избежать этой проблемы — создать постоянные поля TField в исходном наборе данных и убедиться, что первый столбец идентификатора имеет тип ftLargeInt как в вашей таблице DBX, которая обращается к базе данных Sqlite, так и в вашем ClientDataSet.

Кстати № 2, вам не нужны 2 ApplyUpdates в вашем Button1Click, но, кроме этого, ваш код выглядит нормально.

person MartynA    schedule 12.08.2014
comment
Расскажу вам, что случилось... сделал все, как было предложено.... Но потом, когда я удалил запись (пример "-3") из последовательности от -1 до -5, все пошло прахом... Счет сошел с ума ... Новые записи были вставлены с теми же номерами autoinc ... Из-за этого стало не работать приложение обновлений .... В общем - бесполезно. - person user3927897; 18.08.2014
comment
Две вещи: во-первых, я обновил свой ответ, чтобы удалить предположение о том, что столбец идентификатора может иметь разные типы данных в наборах данных DBX и CDS. Я не уверен, откуда я взял эту идею, потому что CDS вызывает исключение, если его тип столбца ID не соответствует типу набора данных DBX. Во-вторых, я думаю, что могу знать, почему вы обнаружили, что весь ад разразился, когда вы удалили запись. Если вы начнете с полностью пустой таблицы в базе данных Sqlite и добавите 3 строки, предположительно их идентификаторы отобразятся в вашем графическом интерфейсе как -1, -2 и -3. Но каковы их значения идентификаторов в БД? - person MartynA; 18.08.2014
comment
Ок, так и думал. Я думаю, что знаю, как это исправить, но, честно говоря, я думаю, что для вас было бы лучше опубликовать новый q, потому что он не в той же точке, что и этот q, который в основном заключается в том, как сохранить записи с автоматическим включением в базу данных. , и требует более длинного ответа, чем поместится здесь в комментарии. Может быть, что-то вроде того, что я следую статье EMB, используя DBX и поле идентификатора ftLargeInt, потому что это то, что требует Sqlite, но мои записи сохраняются в БД с их временными отрицательными идентификационными номерами, и если я попытаюсь удалить один из последовательности новых записей, я получаю хаос - person MartynA; 19.08.2014