【问题标题】:TADOQuery - Edit mode inserts new record rather than editingTADOQuery - 编辑模式插入新记录而不是编辑
【发布时间】:2020-05-30 16:42:54
【问题描述】:

我对@9​​87654322@ 的行为感到困惑,我们就叫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模式。

我在这里做错了什么?

【问题讨论】:

  • 这是自然行为,它是documented"如果数据集为空,Edit 调用 Insert。 否则 Edit"
  • 嗯,我认为这是一个有用的问答,因为行为,无论是否记录在案,都不直观、不直观或令人难忘。
  • 你总是可以在尝试编辑之前检查 EOF,我在这里没有看到问题,这都是记录在案的行为......
  • 正如 MartynA 所说,无论是否记录在案,这仍然是一种奇怪的行为。在我意识到数据集是空的之前,我花了 20 分钟在我的桌子上敲打我的头,试图弄清楚为什么它是插入而不是编辑。一旦我发现它是空的,我很快就找到了原因(一个函数“添加”返回了我的对象,它有一个“ID”参数,虽然提供了,但我从未在该函数中分配它)。
  • 您的代码有缺陷,避免该缺陷(通过检查 EOF)并且不需要 headbanging...

标签: sql delphi ado


【解决方案1】:

我认为记录此行为的 cmets 是不恰当的。文档没有明确说明(可能是因为作者从未想过这一点)是不能保证这种行为是确定性的。

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 代码中的各个点,它通过代码(例如@ 987654323@ 和那种行为根本没有记录在案。因此,经过反思,我认为 Jerry 可能正确地期望尝试编辑不存在的记录应该被视为错误条件,而不是通过默默地调用 Insert 来忽悠它,无论它是否记录在案。

【讨论】:

  • 确实如此。这就像一辆汽车,其文件显示“当您踩下制动踏板时,取决于您行驶的速度,可能会或可能不会应用刹车。”那么为什么不呢?!
【解决方案2】:

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

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

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

【讨论】:

  • "如果数据集为空,Edit 调用 Insert。" (source)
  • “编辑”是一个或多或少包括“插入”、“更新”和“删除”的术语。如果您关心包装器,请直接讨论 SQL。
  • 我的SELECT 已经是 SQL,而且 SQL 已经足够通用了——当我也可以直接使用 SQL 提交数据时,为什么还要打扰 ADO 和它自己的逻辑(UPDATE 变成 INSERT),肯定知道会发生什么?那时 OP 不会感到惊讶(无论是否阅读文档)。
  • @MartynA 我认为他指的是调用显式更新或插入语句,而不是使用编辑/追加/发布。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多