Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 8 of 8 total
Thread TDatabase AutoTransactions is good, but the TransactionLevel is...
Mon, Jun 5 2017 3:28 AMPermanent Link

kentersoft

Sometimes i get customer complain data can't save, but edit and Save all success, no any error,
first i think front session timeout, but save has no any error. Because customer not clear explain it,
until today i self reproduce it, it's two dataset, a master and a detail dataset, if user edit master dataset,
then edit detail dataset, he forget save the master dataset, after finished edit the detail dataset,
he save the detail dataset, he will not see any error, then he think have success save, but not.

actually I use a global TDatabase, it's AutoTransactions is true, so the Transaction is not go to the Request Queue if TDatabase InTransaction(TransactionLevel>=0), so what i can do, in detail dataset's beforeInsert, beforedelete, beforesave event, i can call master dataset's CheckBrowseMode funciton, this will force post the master change, this case is solved.

But is this end, no, my applicaiton use one big TDatabase, i put all dataset on it,
some dataset have master-detail relationship, but most is separate, suppose we have separate dataset1 and
dataset2, two form form1, form2, form1 hook to dataset1, form2 hook to dataset2, in form1, user edit,
FORGET SAVE, click link to navigate to form2, edit, then click save, he will not see any error,
then he continue happy work, but since TransactionLevel is nested, all edit is not actually save to db,
since dataset1, dataset2 is not related, in any save, i can't check another, also there are dozens dataset,
this make it very likely to happen, if any dataset not save, then the next edit will save no error,
but actually not save to db, only in front's transction.

so what i think, in dataset, add a property like JoinToMainTransction: Boolean, default is false,
for separate dataset, when save, Tdatabase Immediately post the tranasction to Request Queue, not check
TDatabase is or not InTransaction, for JoinToMainTransction = True's dataset, check InTransaction,
work as old behavior, this will make front more robust,

another method is make one dataset one database, this will isolation the transaction, but i think is inefficient.

thanks
Mon, Jun 5 2017 4:59 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com


<< But is this end, no, my applicaiton use one big TDatabase, i put all dataset on it,
some dataset have master-detail relationship, but most is separate, suppose we have separate dataset1 and
dataset2, two form form1, form2, form1 hook to dataset1, form2 hook to dataset2, in form1, user edit,
FORGET SAVE, click link to navigate to form2, edit, then click save, he will not see any error,
then he continue happy work, but since TransactionLevel is nested, all edit is not actually save to db,
since dataset1, dataset2 is not related, in any save, i can't check another, also there are dozens dataset,
this make it very likely to happen, if any dataset not save, then the next edit will save no error,
but actually not save to db, only in front's transction. >>

If you have a particularly convoluted editing cycle, with a lot of nesting, then it might be simply easier to handle the transactions manually instead of trying to rely on the TDataSet events to handle them with all of the edge cases.  It certainly will make the code much clearer to follow.

Tim Young
Elevate Software
www.elevatesoft.com
Mon, Jun 5 2017 9:44 PMPermanent Link

kentersoft

<<
If you have a particularly convoluted editing cycle, with a lot of nesting,
>>

No, I don't want any nest transaction, most dataset is alone, because these dataset
put on one TDatabase, then any edit to these dataset will auto make nest transaction,
this is why i suggest add a property to dataset for skip this.

<<
so what i think, in dataset, add a property like JoinToMainTransction: Boolean, default is false,
for separate dataset, when save, Tdatabase Immediately post the tranasction to Request Queu
>>

Hope you understand me!

thanks
Wed, Jun 7 2017 2:02 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

<< No, I don't want any nest transaction, most dataset is alone, because these dataset put on one TDatabase, then any edit to these dataset will auto make nest transaction, this is why i suggest add a property to dataset for skip this. >>

Yes, I understand.  My reference to "nesting" was to the editing sequences, not the transactions themselves.

But, again, my answer is the same: if you want to edit multiple datasets in the same transaction, but don't want nested transactions, etc., then you should use manual transactions.

Automatic transactions are naturally dependent upon nested transactions.  Without the nested transaction level, how will EWB know when to commit the automatic transaction ?

Tim Young
Elevate Software
www.elevatesoft.com
Wed, Jun 7 2017 9:05 PMPermanent Link

kentersoft


<<
Yes, I understand.  My reference to "nesting" was to the editing sequences, not the transactions themselves.
>>

The editing sequences is not important, this is determine by end user.

<<
But, again, my answer is the same: if you want to edit multiple datasets in the same transaction, but don't want nested transactions, etc., then you should use manual transactions.
>>

I make a picture to demo the using scenes, all edit using databind, the IMPORT THING is user *FORGET* click save button, then any other form's subsequent edit will not save(actually the edit not post to backend, but user not know this). I use a TPagePanel to demo this, actual is TBasicPanel embeded child form. If there are more form, the probability will increases dramatically.

<<
Automatic transactions are naturally dependent upon nested transactions.  Without the nested transaction level, how will EWB know when to commit the automatic transaction ?
>>

This is why i suggest TDataSet add a property like JoinToMainTransction: Boolean(default = False), for alone dataset, we set this property to False, when we call TDataset.Save, we not push this transcation to TDatabase's Transaction, but directly goto TServerRequest, for JoinToMainTranscation=True's dataset, we run before logic, push to TDatabase, this will make program more robust.

Hope you can understand me, the decision is on your side.
Thanks



Attachments: Transaction.png
Wed, Jun 14 2017 1:10 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com


<< This is why i suggest TDataSet add a property like JoinToMainTransction: Boolean(default = False), for alone dataset, we set this property to False, when we call TDataset.Save, we not push this transcation to TDatabase's Transaction, but directly goto TServerRequest, for JoinToMainTranscation=True's dataset, we run before logic, push to TDatabase, this will make program more robust. >>

I understand what you're saying, and will have to think about this to see if there are any issues with doing so.

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Jun 23 2017 11:36 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Okay, I looked into this in more detail, and this option:

"another method is make one dataset one database, this will isolation the transaction, but i think is inefficient."

is the best route for you to take.

The only other design that I could come up with was a "TransactionGroup" or "TransactionID" property for the TDataSet component that specified which transaction group that the dataset belonged to.  However, this is just a bunch of extra work to recreate what the TDatabase component is already doing: separating datasets so that they use different transaction/load contexts.

There's nothing to prevent you from using 2 or more TDatabase instances in your application that all point to the same defined database in the Database Manager (or EWB Web Server), yet have different names in your EWB application and use different transaction behaviors.  For example, you could have a "Lookup" database that contains lookup datasets that you don't want to be involved in your transactions on customer datasets.

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Jun 23 2017 11:35 PMPermanent Link

kentersoft

I add a method CommitAll to TDatabase, looks like

procedure TDbMain.CommitAll;
begin
  while TransactionLevel > -1 do Commit;
end;

then in save, i first call this, this will ensure there is no left uncommit transaction,
if current has no better solution, then just let it's as is for now, thanks!
Image