如果用户通过 dbgrid 更改数据,则不会触发 AdoConnection 的 ExecuteCompleted
ExecuteCompleted of AdoConnection is not fired if user changes data via dbgrid
如果我执行类似
的查询
Update Table Set aField = 1 Where tablePk = 1
我可以从AdoConneciton 的ExecuteComplete 事件中获取受影响的记录数(RecordsAffected 参数)。但是,如果我通过 dbgrid 更改数据,则不会触发 ExecuteComplete 事件。
如何在 dbgrid 执行 insert/update/delete 命令后获得受影响的记录数?
我认为没有办法在您进行更新时获取受影响的行数,
通过 TDBgrid 或其他 DB 感知组件(如 TDBNavigator)插入和删除。原因是 DB-aware 控件调用 TDataSet 的 Post 和 Delete 方法,并且这些调用覆盖了 TAdoCustomDataSet 中的 InternalPost 和 InternalDelete。它们的工作方式与通过 TAdoQuery 的 ExecSql 方法执行 SQL 语句的方式完全不同。
根据设计,TDataSet.Post 和 TDataSet.Delete 应该只影响一行,所以如果操作成功,您就会知道只有一行受到影响。
值得注意的是, 有一种方法可以将同一事件处理程序附加到一个数字,尽管对您想要做的事情没有太大帮助
共享 TAdoConnection 的 TAdoCustomDataSet 后代,如以下代码所示:
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
for i := 0 to AdoConnection1.DataSetCount - 1 do
AdoConnection1.DataSets[i].AfterPost := AfterPost;
AdoQuery1.Open;
AdoQuery2.Open;
end;
procedure TForm1.AfterPost(DataSet: TDataSet);
var
Q : TAdoQuery;
begin
if DataSet is TAdoQuery then begin
Q := TAdoQuery(DataSet);
Caption := IntToStr(Q.RowsAffected);
end
else
Caption := 'Post';
end;
当然,如果涉及的数据集已经有自己的事件处理程序,
您将需要一些结构来存储现有的处理程序并链接到
共享处理程序中正确的一个(f.i。TForm1.AfterPost 以上)。
如果您尝试上面的代码并观察当您 post 编辑时会发生什么
从从 TAdoQuery 获取数据的 DBGrid 中,您会不幸地看到,RowsAffected 为零。
那是因为 TAdoQuery 的 FRowsAffected 只在它的时候更新
ExecSql
方法被调用,但数据集操作没有被调用
通过 DBGrid 调用。区别在于 AdoConnection 的
OnExecuteComplete
从用于执行的 Command
对象调用
TAdoQuery 的 ExecSql
。从 DBGrid、otoh、call 发起的操作
在其 InternalPost 和 InternalDelete 中与 TAdoCustomDataSet 关联的 RecordSet
对象的方法,
并且不会调用 AdoConnection 的 OnExecuteComplete
.
RecordSet
对象有自己的事件集,请参阅 f.i。 RecordSetEvents
在 ADOInt.Pas 中,可以想象您可以为以下各项设置共享事件处理程序
那些与上面的共享 AfterPost
事件示例类似的方式。然而,
如果您想获得,我认为那对您没有任何用处
从调用的 TDataset Insert/Update/Delete 的 RowsAffected 值
DBGrid(或者说连接到它的 TDataSource 的 TDBNavigator)。
我这么说的原因是如果你看一下源代码
TAdoCustomDataSet
的 InternalPost
方法你会看到它包括
if State = dsEdit then
UpdateData
else
begin
Recordset.AddNew(EmptyParam, EmptyParam);
try
UpdateData;
except
嵌套的 UpdateData
通过调用
完成它的工作
Recordset.Update(EmptyParam, EmptyParam);
现在,如果您查看 RecordSet.Update 的 MS 文档,您会看到例如
https://msdn.microsoft.com/en-us/library/ecc2bf09.aspx?f=255&MSPPError=-2147217396
清楚地表明,如果 Update
不影响恰好一条记录,则
引发异常。我想这就是@KenWhite 说的时候想到的
"There will only be a single record updated"。所以如果 RecordSet.Update 成功,
你知道只有一排受到影响。
我没检查过,但是因为 TAdoCustomDataSet.InternalDelete
使用它的 Recordset
反对进行删除,类似的情况可能也是如此。
如果我执行类似
的查询Update Table Set aField = 1 Where tablePk = 1
我可以从AdoConneciton 的ExecuteComplete 事件中获取受影响的记录数(RecordsAffected 参数)。但是,如果我通过 dbgrid 更改数据,则不会触发 ExecuteComplete 事件。
如何在 dbgrid 执行 insert/update/delete 命令后获得受影响的记录数?
我认为没有办法在您进行更新时获取受影响的行数, 通过 TDBgrid 或其他 DB 感知组件(如 TDBNavigator)插入和删除。原因是 DB-aware 控件调用 TDataSet 的 Post 和 Delete 方法,并且这些调用覆盖了 TAdoCustomDataSet 中的 InternalPost 和 InternalDelete。它们的工作方式与通过 TAdoQuery 的 ExecSql 方法执行 SQL 语句的方式完全不同。
根据设计,TDataSet.Post 和 TDataSet.Delete 应该只影响一行,所以如果操作成功,您就会知道只有一行受到影响。
值得注意的是, 有一种方法可以将同一事件处理程序附加到一个数字,尽管对您想要做的事情没有太大帮助 共享 TAdoConnection 的 TAdoCustomDataSet 后代,如以下代码所示:
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
begin
for i := 0 to AdoConnection1.DataSetCount - 1 do
AdoConnection1.DataSets[i].AfterPost := AfterPost;
AdoQuery1.Open;
AdoQuery2.Open;
end;
procedure TForm1.AfterPost(DataSet: TDataSet);
var
Q : TAdoQuery;
begin
if DataSet is TAdoQuery then begin
Q := TAdoQuery(DataSet);
Caption := IntToStr(Q.RowsAffected);
end
else
Caption := 'Post';
end;
当然,如果涉及的数据集已经有自己的事件处理程序, 您将需要一些结构来存储现有的处理程序并链接到 共享处理程序中正确的一个(f.i。TForm1.AfterPost 以上)。
如果您尝试上面的代码并观察当您 post 编辑时会发生什么
从从 TAdoQuery 获取数据的 DBGrid 中,您会不幸地看到,RowsAffected 为零。
那是因为 TAdoQuery 的 FRowsAffected 只在它的时候更新
ExecSql
方法被调用,但数据集操作没有被调用
通过 DBGrid 调用。区别在于 AdoConnection 的
OnExecuteComplete
从用于执行的 Command
对象调用
TAdoQuery 的 ExecSql
。从 DBGrid、otoh、call 发起的操作
在其 InternalPost 和 InternalDelete 中与 TAdoCustomDataSet 关联的 RecordSet
对象的方法,
并且不会调用 AdoConnection 的 OnExecuteComplete
.
RecordSet
对象有自己的事件集,请参阅 f.i。 RecordSetEvents
在 ADOInt.Pas 中,可以想象您可以为以下各项设置共享事件处理程序
那些与上面的共享 AfterPost
事件示例类似的方式。然而,
如果您想获得,我认为那对您没有任何用处
从调用的 TDataset Insert/Update/Delete 的 RowsAffected 值
DBGrid(或者说连接到它的 TDataSource 的 TDBNavigator)。
我这么说的原因是如果你看一下源代码
TAdoCustomDataSet
的 InternalPost
方法你会看到它包括
if State = dsEdit then
UpdateData
else
begin
Recordset.AddNew(EmptyParam, EmptyParam);
try
UpdateData;
except
嵌套的 UpdateData
通过调用
Recordset.Update(EmptyParam, EmptyParam);
现在,如果您查看 RecordSet.Update 的 MS 文档,您会看到例如
https://msdn.microsoft.com/en-us/library/ecc2bf09.aspx?f=255&MSPPError=-2147217396
清楚地表明,如果 Update
不影响恰好一条记录,则
引发异常。我想这就是@KenWhite 说的时候想到的
"There will only be a single record updated"。所以如果 RecordSet.Update 成功,
你知道只有一排受到影响。
我没检查过,但是因为 TAdoCustomDataSet.InternalDelete
使用它的 Recordset
反对进行删除,类似的情况可能也是如此。