我希望我的表具有autoinc字段,但使用ClientDataSet对其进行插入会导致“字段必须具有值”错误。似乎Datasnap服务器不知道它应该自己生成一个并期望一个值。 对于演示,我创建了一个只有2个字段的简单表: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问题,我使用了Dr. Bobs的建议:
procedure TForm3.ClientDataSet1NewRecord(DataSet: TDataSet);
const {$J+}
ID: Integer = -1;
begin
DataSet.FieldByName('ID').AsInteger := ID;
DEC(ID) ;
end;
虽然autoinc计数正在倒退,但我可以忍受。但...... 记录会添加到网格中但不会添加到数据库中!?
有人可以请教我如何处理这个autoinc噩梦吗?看到有关使用数据集的onreconcile事件的一些建议,但手动纠正错误不适合我。我尝试为ID字段插入一个零值,希望datasnap服务器能够纠正错误,但它只是闪现调和对话框,所以我可以纠正这个问题。帮助!
端;
答案 0 :(得分:2)
您没有说明您使用哪种数据集将DataSetProvider连接到Sqlite数据库。我想它不是FireDac数据集,因为它们正确处理Sqlite表中的autoinc列。
所以假设你正在使用其他类型,我认为你可能忽略了勘误部分的重要性
http://edn.embarcadero.com/article/20847
在评论中提到的文章,其中说:
“对于未将其自动增量字段映射到TAutoIncField的DBMS,您需要删除源数据集上的TField.ProviderFlags.pfInUpdate标志,以允许DataSnap将记录解析回数据库。您真的在做这与DataSnap为TAutoIncFields自动执行的操作相同。“
这适用于Sqlite。除此之外,您需要做的是在源数据集字段不是持久数据库字段的情况下,在运行时检查源数据集的列类型(我的意思是,提供DataSetProvider的列类型)。
对于Sqlite,源数据集字段类型应为ftLargeInt,而不是ftAutoInc,因为Sqlite数据库中的autoinc列大小为64位,而不是32位(这是ftAutoinc假设的)。避免此问题的最简单方法是在源数据集上创建持久性TField,并确保ID列一个在访问Sqlite数据库和ClientDataSet的DBX表中键入ftLargeInt。
Btw#2,你在Button1Click中不需要2个ApplyUpdates,但除此之外,你的代码似乎没问题。