问题描述
我希望我的表具有autoinc字段,但是使用ClientDataSet对其进行插入会导致字段必须具有值错误。似乎Datasnap服务器不知道它应该自己生成一个并期望值。
对于该演示,我创建了一个仅包含2个字段的简单表:ID(autoinc)和DATE(varchar)。
数据库是SQLite。
过程TForm3.Button1Click(Sender:TObject);
开始
ClientDataSet1.Insert;
ClientDataSet1.FieldByName('DATE')。Value:= DateUtils.DateOf(PlannerCalendar1.Date);
ClientDataSet1.Post;
ClientDataSet1.ApplyUpdates(0);
如果ClientDataSet1.ApplyUpdates(0)= 0,则
ClientDataSet1.Refresh;
为了解决autoinc问题,我使用了Bobs博士的建议:
程序TForm3.ClientDataSet1NewRecord(DataSet:TDataSet);
const {$ J +}
ID:整数= -1;
开始
DataSet.FieldByName(’ID’)。AsInteger:= ID;
DEC(ID);
结尾;
尽管autoinc的数量倒退了,但我可以接受。但是...
记录被添加到网格中,而不是数据库中!!
所以有人可以启发我如何应对这种autoinc噩梦吗?看到了一些有关使用数据集的onreconcile事件的建议,但手动更正错误不适合我。我尝试为ID字段插入一个零值,希望datasnap服务器可以纠正该错误,但是它所做的只是让我看到协调对话框,以便我可以解决此问题。
end;
您不说什么用于将DataSetProvider连接到Sqlite数据库的一种数据集。我想这不是一个FireDac数据集,因为它们正确处理了Sqlite表中的autoinc列。
勘误部分的重要性 nofollow> http://edn.embarcadero.com/article/20847
在评论中提到的文章,其内容为:
对于未将其自动增量字段映射到TAutoIncField的DBMS,您需要删除源数据集上的TField.ProviderFlags.pfInUpdate标志,以允许DataSnap解析记录回到数据库。您实际上在做与DataSnap通过TAutoIncFields自动为TAutoIncFields做的相同的事情。
这适用于Sqlite。除此之外,如果源数据集字段不是持久性字段,那么您需要在运行时检查源数据集的列类型(我的意思是,该类型将数据提供给DataSetProvider)。
对于Sqlite,源数据集字段类型应为ftLargeInt,而不是ftAutoInc,因为Sqlite数据库中的autoinc列大小为64位,而不是32位(是ftAutoinc假定的)。避免此问题的最简单方法是在源数据集上创建持久性TField,并确保ID列之一在访问Sqlite数据库的DBX表和ClientDataSet中都为ftLargeInt。
Btw#2,您不需要Button1Click中的2个ApplyUpdates,但是除此之外,您的代码似乎还不错。
I would like my table to have the autoinc field but doing an insert on it using ClientDataSet causes 'field must have value' error. It seems Datasnap server does not know it should generate one by itself and expects a value.For the demo I created a simple table with only 2 fields : ID (autoinc) and DATE (varchar).The database is 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;
To deal with the autoinc issue I used Dr. Bobs suggestion:
procedure TForm3.ClientDataSet1NewRecord(DataSet: TDataSet);
const {$J+}
ID: Integer = -1;
begin
DataSet.FieldByName('ID').AsInteger := ID;
DEC(ID) ;
end;
Though autoinc count is going backwards, I can live with that. But ...Records get added in the grid but not in the database !?
So can someone please enlighten me on how to deal with this autoinc nightmare? Seen some suggestions on using the onreconcile event of the dataset but manually correcting the error is not for me. I tried inserting a zero value for the ID field hoping that datasnap server would correct the error but all it does is flash me the reconcile dialog so I can correct the issue. Help !
end;
You don't say what kind of dataset you're using to connect your DataSetProvider to the Sqlite database. I imagine it's not a FireDac dataset, because they handle autoinc columns in Sqlite tables correctly.
So assuming you're using some other type, I think you may have overlooked the significance of the Errata section of the
http://edn.embarcadero.com/article/20847
article that has been mentioned in comments, where it says:
"For DBMSes that don't map their auto increment fields to TAutoIncField, you need to remove the TField.ProviderFlags.pfInUpdate flag on the source dataset to allow DataSnap to resolve the record back to the database. You're really doing the same thing that DataSnap does automatically for TAutoIncFields by doing this. "
This applies to Sqlite. As well as that, what you need to do is to inspect the column type of your source dataset (I mean, the one feeding your DataSetProvider), at run-time if your source dataset fields aren't persistent ones.
For Sqlite, the source dataset field type should be ftLargeInt, not ftAutoInc, because the autoinc column size in the Sqlite database is 64-bit, not 32-bit (which is what ftAutoinc assumes). The easiest way to avoid this problem is to create persistent TFields on your source dataset and make sure the ID column one is type ftLargeInt in both your DBX table that accesses the Sqlite database and your ClientDataSet.
Btw #2, you don't need the 2 ApplyUpdates in your Button1Click, but apart from that, your code seems fine.
这篇关于DataSnap和autoinc字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!