三层的数据更新的问题

ilang 2002-12-12 07:21:06
三层结构,新增一个记录后保存,正常,再修改时发现数据无论如何都更新不进去了,出错信息是‘Record not found or changed by another user’,在cds.ApplyUpdates后面加上cds.Refresh,可以保存,但换了一个复杂一点的表(有日期或浮点型字段的大概),问题又出现了,不知道谁有没有碰到这种情况,有什么办法解决?
BTW:试过最简单的三层结构,只写了两句更新数据的代码,也会这样
...全文
112 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
ytwxw 2002-12-17
  • 打赏
  • 举报
回复
up
ilang 2002-12-17
  • 打赏
  • 举报
回复
结束
lizongqi 2002-12-16
  • 打赏
  • 举报
回复
我都是自己更新
ilang 2002-12-16
  • 打赏
  • 举报
回复
还没有完全解决 以下的可以解决标识列的问题
设置应用层相应的TDataSetProvider的UpdateMode为upWhereKeyOnly,然后在其BeforeUpdateRecord事件中
var
I, J: Integer;
begin
with DeltaDS do
begin
for I := 0 to RecordCount-1 do
begin
for J := 0 to FieldCount-1 do
begin
with Fields[J] do
if not (pfInKey in ProviderFlags) and not (FieldName='id') then ProviderFlags := ProviderFlags + [pfInKey];
end;
end;
end;
end;
//id为标识列名称
//如果保留数据库中的默认值,在TClientDataSet的ApplyUpdates语句后加上Refresh
但是有时候Refresh会出问题,???
chechy 2002-12-13
  • 打赏
  • 举报
回复
如果是自增列,需要将pfInUpdate去掉。可以保留pfInWhere
ilang 2002-12-13
  • 打赏
  • 举报
回复
气死我了 刚才打了半天的一段被我不小心按了个后退键竟然莫名其妙的没有了

继续

就说主明细表结构的问题好了,明细表中没有设主键,所以没办法找一个可以设置pfInWhere为True的字段,和主表关联的那个字段肯定是不行的,随便用一个其他的字段,同时更新几条子表记录时会出现这样的问题:如果是待更新的几条记录中该字段的值一样,则只会更新一条记录上去(如果不一样就没有问题),我现在需要保留数据库中的标识列(虽然我很现在讨厌这些东西),除了给所有的表加一个主键还有没有其他方法?
ilang 2002-12-13
  • 打赏
  • 举报
回复
我找到罪魁寇首了!就是数据库中的标识列和默认值!害我昨天晚上又花了一个晚上时间:(
通常情况下即使有浮点型字段或者日期字段也是可以更新的,偏偏我那天选择测试的一个数据表中有一个标识列,所以我还以为是比较普遍的问题
现在原因是清楚了,很明显,提交含有标识列(自增)或默认值的数据表的记录时,SQL SERVER会自动给这些字段赋值,更改记录,所以系统就定位不到这些记录了,出现‘record has changed’异常

比较彻底的解决方法是删除数据库中的所有标识列同时去除所有的默认值

按照 chechy的方法可以解决有主键的单表的问题,我是这样处理的,因为是在TClientDataSet的CommandText里边写SQL语句连接数据表的,所以直接在TClientDataSet的字段列表中设置ProvierFlags属性不行,需要在应用层的相应的TDataSetProvider的
BeforeUpdateRecords事件中写代码

var
I, J: Integer;
begin
with DeltaDS do
begin
for I := 0 to RecordCount-1 do
for J := 0 to FieldCount-1 do
with Fields[J] do
if (pfInWhere in ProvierFlags) and not (FiledName = 'iNo') then ProvierFlags := ProvierFlags - [pfInWhere];
end;
end;

但是现在问题还只解决了一部分
如果是没有主键并且批量更新或者是主明细表结构(没有给明细表设主键),这时候新的问题又出来了,事实上也是小小提到的这个限制:必段将唯一识别字段例入永久字段例里


ilang 2002-12-12
  • 打赏
  • 举报
回复
to 小小
多谢
to chechy
多谢
我回去试一下 可以的话就发分
ihihonline 2002-12-12
  • 打赏
  • 举报
回复
不好意思。没有刷新页面就回答了;和上面 的所说的基本相似;这是一种通用的方法,在多层中,强调ProvierFlags的用法很重要,主要就是对效率上的应用;你应该首先明确,你调用ApplyUpdate默认是数据库自动产生的SQL 语句,当它不能确定你的更新记录时,或是模糊的时候,就会出现如上的那种情况,具体的就是一些精度和大文本型更新定位,其实,你同样可以利用另一种方法,你可以在远程进行手动的更新,事物可以自己处理,也可以交给数据库服务器处理,手动更新的方法有时更来效;具体的更新方法,有很多的例程;或是我的坛子上有这方面的详细说明,而且是多表更新,但是需要说明的一点就是你必段将唯一识别字段例入永久字段例里,不然,Delta or Data不会进行处理,出错就更显而易见
ihihonline 2002-12-12
  • 打赏
  • 举报
回复
的确,如Chechy所说,这是问题的关键,还有一种不算很好的办法就是你应该多有一个可以唯一标识的永久字段,你可以将其隐藏起来,对于用户来说,是完全透明的,只要设定其ProviderFlags就可以了
chechy 2002-12-12
  • 打赏
  • 举报
回复
解决这个问题的方法很简单,需要修改每个Field的ProviderFlags属性,除了主键需要有pfInWhere以外,其它字段都去掉pfInWhere这个选项。这样Delphi生成的Where语句就不会出现不能定位的情况。(需要在TQuery中修改每个Field的属性)。
这样就可以了。Good Luck。
chechy 2002-12-12
  • 打赏
  • 举报
回复
出现这个问题的主要原因是该表中有浮点、日期、memo或者BOLB等类型的字段。
在默认得情况下,Delphi会自动生成提交数据自动生成SQL,由于insert没有where语句,所以肯定成功。而where中如果有这些类型,SQL就无法准确定位记录,当记录不能定位时,只好报错“Record not found or changed by another user”(因为Delphi以为记录被别的用户修改了)。
chechy 2002-12-12
  • 打赏
  • 举报
回复
呵呵,这个问题似乎经常有人问,其实这个问题解决不难,但是说起来太复杂。
ihihonline 2002-12-12
  • 打赏
  • 举报
回复
...
jing lai zai shuo

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧