Search code examples
delphidlltransactionsdatabase-connectionfiredac

Transaction in shared Firedac Connection Between an Application and a DLL


According Embarcadero:

The application connection does not track state changes performed by the DLL. Therefore, the DLL should preserve the same transaction state as it had before the DLL call. It is indicated not to handle transactions in a DLL, change the transaction isolation level and other settings in a DLL.

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/DLL_Development_(FireDAC)

It says that is not indicated handle transactions in a DLL, because the application does not track state changes performed by the DLL. Can someone elaborate on that?

If I handle transactions in a DLL, what will happen?


Solution

  • Nothing special. Transaction operations that you execute on shared connection object inside DLL will be performed. You should just be careful, nothing more than that. First thing is that you should keep the transaction state same as before a DLL function call. Second thing is that you should not change transaction settings from within a DLL function context:

    1. Preserve the same transaction state

    You're free to explicitly handle transactions by yourself inside a DLL, but it is recommended to not do so because of possible mistake you can make. Imagine a DLL function which, by mistake, only starts a transaction:

    procedure DoSomething(Handle: Pointer); stdcall;
    var
      Connection: TFDConnection;
    begin
      Connection := TFDConnection.Create(nil);
      try
        Connection.SharedCliHandle := Handle;
        Connection.Open;
        Connection.StartTransaction;
      finally
        Connection.Free;
      end;
    end;
    

    And your application will execute this:

    FDConnection1.StartTransaction;
    try
      DoSomething(FDConnection1.CliHandle);
      FDConnection1.Commit;
    except
      FDConnection1.Rollback;
      raise;
    end;
    

    Now, as a result of such code execution is that you'll have started extra nested transaction which the application connection object is not aware of (that's because the transaction state changes are not tracked) hence for DBMS, transaction started inside that malformed DLL never ends. So that's what you need to take care of.

    If there was transaction state change tracking implemented for these cases, application connection object would be aware of that pending transaction and could finish it, e.g. when closing connection.

    2. Preserve transaction isolation level and other settings

    Similarly one can break e.g. finishing of the transaction started by the application connection object when changing isolation level settings from within a DLL function.