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 来蒙混过关,无论它是否记录在案。
我对 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 来蒙混过关,无论它是否记录在案。