我对 的行为感到困惑TADOQuery
,让我们调用Q
. 当我使用Q.Edit
, 填充一些字段,然后Post
,它最终实际上插入了一条新记录。
代码很简单,从对象中读取ID:
Q.SQL.Text := 'select * from SomeTable where ID = :id';
Q.Parameters.ParamValues['id'] := MyObject.ID;
Q.Open;
try
Q.Edit;
try
Q['SomeField']:= MyObject.SomeField;
finally
Q.Post;
end;
finally
Q.Close;
end;
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,它决定插入一条新记录,而不是更新预期的记录。单步执行代码,紧跟在 之后Q.Edit
,查询实际上处于Insert
模式。
我在这里做错了什么?
我认为记录这种行为的评论是离题的。文档没有明确说明(可能是因为作者从未想到过这一点)是不能保证这种行为是确定性的。
TDataSet.Edit 的内部结构几十年来几乎没有改变。这是西雅图版本:
procedure TDataSet.Edit;
begin
if not (State in [dsEdit, dsInsert]) then
if FRecordCount = 0 then Insert else
begin
CheckBrowseMode;
CheckCanModify;
DoBeforeEdit;
CheckParentState;
CheckOperation(InternalEdit, FOnEditError);
GetCalcFields(ActiveBuffer);
SetState(dsEdit);
DataEvent(deRecordChange, 0);
DoAfterEdit;
end;
end;
Run Code Online (Sandbox Code Playgroud)
现在,请注意,if .. then ..
基于 FRecordCount 的值,在 TDataSet 代码中的不同点,它被诸如 in 之类的代码强制具有给定的假定值(各种 1、0 或其他值),SetBufferCount
并且该行为未记录在案在所有。因此,经过反思,我认为 Jerry 可能认为尝试编辑不存在的记录应该被视为错误条件是正确的,而不是通过无声地调用 Insert 而不管它是否记录在案。