I am converting a program from Delphi 2005 to Delphi XE2 or XE3.
It uses DbExpress with a Firebird database.
The program uses TSQLQuery.TransactionLevel to allow it to have overlapping transactions.
It is dependent on these overlapping transactions.
(There are actually multiple programs. They all use the same code to access the database. Several run in parallel and communicate occasionally using COM. They each have their own TSQLConnection and database access is all from the main thread. One of the programs runs on a device with an intermittent RF network connection and is able to recover from network dropouts).
TSQLQuery no longer has the TransactionLevel property in Delphi XE2 and XE3.
How can I get overlapping transactions in Delphi XE2 without having multiple connections to the database? I will use multiple connections if there is no alternative, but it won't be a trivial change.
Note that I am referring to overlapping transactions, not nested transactions. Here is an example, minus the checks and try-finallys. This works in Delphi 6 and Delphi 2005.
procedure TForm1.Test7;
var SQLConnection: TSQLConnection;
Transaction1, Transaction2: TTransactionDesc;
Query1, Query2, Query3: TSQLQuery;
begin
SQLConnection := TSQLConnection.Create(nil);
InitialiseFirebirdConnection(SQLConnection);
SQLConnection.Open;
Transaction1.GlobalID := 0;
Transaction1.IsolationLevel := xilREADCOMMITTED;
Transaction1.CustomIsolation := 0;
Transaction1.TransactionId := 7;
Transaction2.GlobalID := 0;
Transaction2.IsolationLevel := xilREADCOMMITTED;
Transaction2.CustomIsolation := 0;
Transaction2.TransactionId := 8;
SQLConnection.StartTransaction(Transaction1);
SQLConnection.StartTransaction(Transaction2);
Query1 := TSQLQuery.Create(nil);
Query1.SQLConnection := SQLConnection;
Query1.SQL.Add('Update "WIDGET" Set "NAME" = ''AAA'' Where "WIDGETID" = 101');
Query1.TransactionLevel := Transaction1.TransactionId;
Query1.ExecSQL;
Query1.Free;
Query2 := TSQLQuery.Create(nil);
Query2.SQLConnection := SQLConnection;
Query2.SQL.Add('Update "WIDGET" Set "NAME" = ''BBB'' Where "WIDGETID" = 102');
Query2.TransactionLevel := Transaction2.TransactionId;
Query2.ExecSQL;
Query2.Free;
Query3 := TSQLQuery.Create(nil);
Query3.SQLConnection := SQLConnection;
Query3.SQL.Add('Update "WIDGET" Set "NAME" = ''CCC'' Where "WIDGETID" = 103');
Query3.TransactionLevel := Transaction1.TransactionId;
Query3.ExecSQL;
Query3.Free;
if Tran1CheckBox.Checked then
SQLConnection.Commit(Transaction1)
else
SQLConnection.Rollback(Transaction1);
if Tran2CheckBox.Checked then
SQLConnection.Commit(Transaction2)
else
SQLConnection.Rollback(Transaction2);
SQLConnection.Close;
SQLConnection.Free;
end;
If you look up "Managing Transactions" in the XE2 Help file, it still describes how "... If you are using TSQLConnection with an InterBase database, you can identify each dataset in your application with a particular active transaction, by setting its TransactionLevel property. That is, after starting a second transaction, you can continue to work with both transactions simultaneously, simply by associating a dataset with the transaction you want."
It's a large program so I really don't want to change technologies or do major re-engineering. I am hoping there might be some other way set the transaction id of a transaction, and to associate a query with a particular transaction.