TADOQuery - 编辑模式插入新记录而不是编辑

TADOQuery - Edit mode inserts new record rather than editing

我对 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;

令我惊讶的是,它没有更新预期的记录,而是决定插入一条新记录。单步执行代码,在 Q.Edit 之后,查询实际上处于 Insert 模式。

我在这里做错了什么?

我同时发布了一个问题和一个答案,因为问题的起因是完全出乎意料的行为,肯定其他人也发生过同样令人困惑的事情。

如果您尝试编辑的数据集没有任何记录,就会发生这种情况。就个人而言,我认为它应该产生一个异常,当没有记录时你不能编辑。但是 TADOQuery 决定附加一条新记录。

这个问题的根本原因是我提供 ID 的对象实际上有一个值 0,因此由于数据库中没有 ID 为 0 的记录,它没有返回。

我认为记录了此行为的评论离题了。文档 don't 明确指出(可能是因为作者从未想过这一点)是不能保证这种行为是确定性的。

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;

现在,请注意 if .. then .. 以 FRecordCount 的值为基础,它在 TDataSet 代码的不同点被代码强制具有给定的假定值(各种 1、0 或其他)例如 SetBufferCount 行为根本 没有记录。因此,经过反思,我认为 Jerry 可能正确地期望尝试编辑不存在的记录应该被视为错误条件,而不是通过静默调用 Insert 来蒙混过关,无论它是否记录在案。