0

I have a query that returns rows with an outer join. This causes records to exist in the results that don't really exist in the table. When those rows are changed FireDac sees the change as an Update instead of an insert. That behavior makes sense from FireDac's side because it has no way to tell the difference.

I am overriding the OnUpdateRecord event to catch those rows that are marked wrong and perform the insert myself. That part is working great. What I can't figure out is how to tell FireDac to perform it's normal process on other records. I thought I could set the AAction to eaDefault and on the return FireDac would continue to process the row as normal. However, that does not seem to be the case. Once OnUpdateRecord is in place it looks like FireDac never does any updates to the server.

Is there a way to tell FireDac to update the current row? Either in the OnUpdateRecord function by calling something - or maybe a different return value that I missed?

Otherwise is there a different way to change these updates into inserts? I looked at changing the UpdateStatus but that is read only. I looked at TFDUpdateSql - but I could not figure out a way how to only sometimes turn the update into an insert.

I am using CachedUpdates if that makes any difference.

Here is what I have for an OnUpdateRecord function:

procedure TMaintainUserAccountsData.QueryDrowssapRolesUpdateRecord(
  ASender: TDataSet; ARequest: TFDUpdateRequest; var AAction: TFDErrorAction;
  AOptions: TFDUpdateRowOptions);
{^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^}
begin
  if (ARequest = arUpdate) and VarIsNull(ASender.FieldByName('Username').OldValue) then
  begin
    ASender.Edit;
    ASender.FieldByName('RoleTypeID').Value := ASender.FieldByName('RealRoleTypeID').Value;
    ASender.Post;
    MGRDataAccess.ExecSQL('INSERT INTO DrowssapRoles (Username, RoleTypeID, HasRole) VALUES (:Username, :RoleTypeID, :HasRole)',
                          [ASender.FieldByName('Username').AsString, ASender.FieldByName('RoleTypeID').AsInteger,
                             ASender.FieldByName('HasRole').AsBoolean]);

    AAction := eaApplied;
  end
  else
  begin
    // What do I do here to get the default FireDac actions?
  end;
end;
Ken White
  • 123,280
  • 14
  • 225
  • 444
Mark Elder
  • 3,987
  • 1
  • 31
  • 47
  • "I could not figure out a way how to only sometimes turn the update into an insert." When I read the intro to your q, I was wondering whether you'd considered `TFDUpdateSql`. Pardon the obvious question, but have you considered whether/how to construct a SQL statement which contains the conditionality necessary to do the necessary? Which SQL back-end, btw? – MartynA Jun 21 '16 at 22:11
  • @MartynA - I'm using MS Access as the backend. So my flexibility in having the SQL statement switch between an insert or update statement is very limited. – Mark Elder Jun 21 '16 at 22:28
  • Use TFDUpdateSql to do your default work and OnUpdateRecord to override that. If OnUpdateRecord does NOT change AAction it will hit TFDUpdateSql next. – FredS Jun 22 '16 at 01:07
  • You may need to set AAction := eaDefault, see the bug report I just filed for details: https://quality.embarcadero.com/browse/RSP-15310 – FredS Jun 22 '16 at 19:54
  • I still could not get it to work using eaDefault. I see the same thing you are seeing regarding the action being set incorrectly before calling the event. But both options are treated the same after the event. For not I just dealt with all my possible option in OnUpdateRecord. I still would like to be able to call the default actions. TFDUpdateSQL still requires that I handle all cases. – Mark Elder Jun 26 '16 at 01:29

0 Answers0