Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TADOQuery - Edit mode inserts new record rather than editing

Tags:

sql

delphi

ado

I'm puzzled at the behavior of the TADOQuery, let's just call Q. When I use Q.Edit, populate some fields, then Post, it ends up actually inserting a new record.

The code is simple, and reading the ID from an object:

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;

To my surprise, rather than updating the intended record, it decided to insert a new record. Stepping through the code, immediately after Q.Edit, the query is actually in Insert mode.

What could I be doing wrong here?

like image 861
Jerry Dodge Avatar asked May 30 '20 16:05

Jerry Dodge


1 Answers

I think the comments that this behaviour is documented are off the point. What the docs don't make clear (possibly because the point never occurred to the author) is that this behaviour is not guaranteed to be deterministic.

The innards of TDataSet.Edit have scarcely changed in decades. Here is the Seattle version:

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;

Now, notice that the if .. then .. is predicated on the value of FRecordCount, which at various points in the TDataSet code is forced to have a given assumed value (variously 1, 0 or something else) by code such as in SetBufferCount and that behaviour isn't documented at all. So on reflection I think Jerry was probably right to expect that attempting to edit a non-existent record should be treated as an error condition, and not be fudged around by silently calling Insert whether or not it is documented.

like image 176
MartynA Avatar answered Oct 02 '22 14:10

MartynA