I think it goes more into UniDAC configuration. Not sure exactly how AutoCommit behaves, but if there is a transaction open, I guess UniDac will detect it and would not perform a commit.
AutoCommit causes, that every insert/update/delete will be commited immediately, UniDAC help :
Use the AutoCommit property to permit or prevent permanent updates, insertions, and deletions of data against the database server without explicit calls to Commit or Rollback methods.
Set AutoCommit to True to permit implicit call to Commit method after every database access. The default value is True.
If I set AutoCommit to true, it works, But I really hoped I get a real transaction handling running :) I'll do some more tests. Atm I get the data saved with AutoCommit.
you wrote "you can read TUniConnection.InTransaction property to be sure of that" (damn, this forum needs a quoting mechanism :) )
Do I have access to it ? I can't use the UniConnection of the DataModule Aurelius created because you clone it and use the clone :P I get only an interface and this interface doesn't offer access to the component.
I'll keep you posted
Helge
I believe AutoCommit is ignored if a transaction is active. It only affects SQL statement executed with no transaction active. Why you need to set if off, then?
I will add 2 screenshots of the SQL monitor when executing the code shown above
Correction, point 2 is wrong, no data is commited
Btw. the reason seems to be :
AureliusConnection1.CloningMode = TCloningMode.Owner;
var Con := (AureliusConnection as IDBConnectionAdapter).AdaptedConnection as TUniConnection;
if Con.InTransaction then
Con.Commit;
That's ugly and should not be used. Are you sure it's not UniDAC which opens the transaction automatically? Are you leaving the original TUniConnection connected? What happens if you keep it disconnected?
Atm I have 3 units where I use anything from the database (the dbmon shows me, that Aurelius does some stuff on the system tables, i think, that happens when i call
TDatabaseManager.Update(AureliusConnection);
procedure TDBA_Databases.PrepareSyncData(const AData: TRtcRecord);
begin
var vtDataDB := AData.NewDataSet(RTC_STRING_DATABASES);
adsDbData.Manager := ObjectManager;
adsDbData.SetSourceCriteria(ObjectManager.Find<TDB_DATA>
.Where(Linq['ServerId'] = AData.asInteger[RTC_STRING_SERVERID]));
adsDbData.Open;
vtData.EmptyTable;
adsDbData.First;
While not adsDbData.Eof do begin
vtData.Append;
vtDataID.AsInteger := adsDbData.FieldByName('Id').AsInteger;
vtDataName.AsString := adsDbData.FieldByName('Name').AsString;
// some more stuff here
vtData.Post;
adsDbData.Next;
end;
DelphiDataSetToRTC(vtData, vtDataDb);
adsDbData.Close;
vtData.EmptyTable;
end;
procedure TDBA_ServerLicense.Internal_InitModule;
var Results : TObjectList<TLICENSE_DATA>;
Item: TLICENSE_DATA;
begin
FbForceSync := False;
inherited;
Results := ObjectManager.Find<TLICENSE_DATA>.List;
For Item In Results Do begin
// if one of the licenses wasn't synced within the last 30 days or has still
// no valid ServerId (Field Id < 0), then we need to sync
If Not FbForceSync Then
FbForceSync := ((Item.ID < 0) Or (DaysBetween(Now, Item.LAST_SYNC) > 30));
RefreshLicenseData(Item);
end;
Results.Free;
end;
After reading a lot of this, I see that first, UniDac seems to have changed its behavior over their versions. Our tests running an old version behaves differently then newer ones.
Trans := FConnection.BeginTransaction;
TDatabaseManager.Update(FConnection);
Trans.Commit;
Wagner R. Landgraf2019-01-16 12:15:20
Were you able to reproduce the problem on your end with my code ?
lol, we posted the same minute :) Thanks for the reply, i adjusted the code accordingly and it behaves as expected.
But if you are using one unit of work at each time, what is the problem of opening a transaction, doing your work, and closing the transaction? You have 1000+ forms but each form (or a combination of a few forms) will have its own unit of work and thus its own start/commit sequence. Why do you need to use a different transaction for it?
Because if I understand it right, Aurelius does the following :
var MyData := FObjectManager.Find<TMyData>(MyId);
If Assigned(MyData) Then begin
// do some update stuff
// FObjectmanager.Flush(MyData);
end else begin
MyData := TMyData.Create;
// assign the new data
FObjectManager.Save(MyData);
end
Ok, I understand.