DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: szliyu112358
今日帖子: 52
在线用户: 11
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/8 23:42:42
标题:
Datasnap FireDAC FDQuery.ApplyUpdate异常问题 浏览:2001
加入我的收藏
楼主: var
  dStrm : TMemoryStream;
begin   
      fDQry.Close;
      fDQry.SQL.Clear;
      fDQry.CachedUpdates := True;
      fDQry.UpdateOptions.KeyFields := 'AF001';//多个主键用分号(;)隔开
      fDQry.UpdateOptions.UpdateTableName := 'ATable';
      fDQry.SQL.Text := 'select * from ATable where 1=0';
      fDQry.Open;

      dStrm := CopyStream(fStream); //fStream从客户端传过来的数据流,经过检测,是正确的客户端数据包
      dStrm.Position := 0;
      fDQry.LoadFromStream(dStrm,TFDStorageFormat.sfBinary);

      fDQry.ApplyUpdates;//执行到这里抛出如下的异常信息,数据更新失败
      fDQry.CommitUpdates;
end;

异常信息:
First chance exception at $7532C54F. Exception class EMSSQLNativeException with message '[FireDAC][Phys][ODBC][SQLSRV32.DLL] SQL_NO_DATA'. Process XXX.exe (6376)
First chance exception at $7532C54F. Exception class EFDException with message '[FireDAC][DApt]-400. Update command updated [0] instead of [1] record. Possible reasons: update table does not have PK or row identifier, record has been changed/deleted by another user'. Process XXX.exe (6376)

根据信息检测,对应主键的数据没有被其他用户占用,没有被删除,客户端传过来的数据包有修改,即changcount>0。但是执行更新,却更新不了。
----------------------------------------------
Everyone will to do best!
作者:
男 hnxxcxg (咏南中间件) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 7:56:33
1楼: 数据表可有主键?客户端fdmemetable1.cacheupdate:=true?
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 8:04:42
2楼: 主键和表名,都是正确的!
也设置好了属性fdmemetable1.cacheupdate:=true;
----------------------------------------------
Everyone will to do best!
作者:
男 earthsbest (全能中间件) ▲▲▲▲△ -
普通会员
2019/9/9 9:05:57
3楼: 如果表有触发器有两种方法解决:
1、设置 FDQuery1.UpdateOptions.CountUpdatedRecords := False;
2、触发器中加上 SET NOCOUNT ON。
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 10:27:15
4楼: earthsbest (全能中间件)

我这个数据库里,没有建立触发器!
----------------------------------------------
Everyone will to do best!
作者:
男 nickemma (N.E Zhou) ★☆☆☆☆ -
普通会员
2019/9/9 13:55:46
5楼: 请看ApplyUpdates的官方解释:
http://docwiki.embarcadero.com/RADStudio/Rio/en/Caching_Updates_(FireDAC)

Reviewing Errors
If an error happens inside the ApplyUpdates call, then ApplyUpdates records the error into the internal data record structure and continues to process updates until the number of errors will be equal to or greater than AMaxErrors. ApplyUpdates does not raise exceptions. To process all erroneous records after the ApplyUpdates call, use either reconciling process, either filter erroneous records.
To reconcile records, assign the OnReconcileError event handler and call the Reconcile method. The OnReconcileError event handler allows analyzing error, reading / changing the current record field values. On exit, it should assign action, which action the FireDAC code should take on the current record with the error. After the Reconcile method calls, ApplyUpdates may be called again to try to post erroneous record changes.
To filter erroneous records, include rtHasErrors into FilterChanges. Then navigate through the dataset and read the RowError property to get an exception object associated with the current record. For example:

var
  oErr: EFDException;
...
if FDQuery1.ApplyUpdates > 0 then begin
  FDQuery1.FilterChanges := [rtModified, rtInserted, rtDeleted, rtHasErrors];
  try
    FDQuery1.First;
    while not FDQuery1.Eof do begin
      oErr := FDQuery1.RowError;
      if oErr <> nil then begin
        // process exception object
        ...
      end;
      FDQuery1.Next;
    end;
  finally
    FDQuery1.FilterChanges := [rtUnmodified, rtModified, rtInserted];
  end;
end;

按我理解ApplyUpdates是不会触发异常的,你试试按官方的例子改一下,看看究竟哪里出现问题吧:
ShowMessage(oErr.Message);
----------------------------------------------
-
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 15:34:36
6楼:  nickemma (N.E)

是设置断点跟踪的时候,执行到FDQuery1.ApplyUpdates时,触发异常。
FDQuery1.ApplyUpdates返回值是1,如果返回值是0,则表示执行FDQuery1.ApplyUpdates成功!
----------------------------------------------
Everyone will to do best!
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 18:45:08
7楼: 郁闷啊!
不知道是不是数据库的问题,重新建立一下主键,再来执行保存,则可以保存正常!
但是之前一建立主键之后就没有改过,也能正常更新一段时间,但是后面就出现这个更新不了的问题。
----------------------------------------------
Everyone will to do best!
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 20:37:45
8楼: 还有,FireDAC对于MSSQL数据库的bit类型字段处理得不好,不能存在空值,或者干脆换成int类型。这样就不会出现以上的异常信息,就能正常保存数据了!
----------------------------------------------
Everyone will to do best!
作者:
男 nickemma (N.E Zhou) ★☆☆☆☆ -
普通会员
2019/9/9 21:13:37
9楼: @grjs_2004

MS SQL2000的Bit用0 ,1 代表False 与 True
----------------------------------------------
-
作者:
男 grjs_2004 (grjsITname) ★☆☆☆☆ -
盒子活跃会员
2019/9/9 21:14:28
10楼: 应该是delphi XE改之后改过来了吧!
----------------------------------------------
Everyone will to do best!
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行70.3125毫秒 RSS