UnitOfWork2 AutoCommit

Posts   
 
    
Marcus avatar
Marcus
User
Posts: 747
Joined: 23-Apr-2004
# Posted on: 01-Jan-2005 16:03:47   

I find myself using the following autoCommit paramater for UnitOfWork and was wondering why this was not made the default behaviour when autoCommit is not specified...

UnitOfWork2 uow = new UnitOfWork2();
// Do Some Work
uow.Commit(adapter, !adapter.IsTransactionInProgress);

I think it makes more sense than leaving the transaction in progress by default.

Just comment! wink

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 01-Jan-2005 17:12:07   

You mean, it should autocommit unless specified otherwise?

Frans Bouma | Lead developer LLBLGen Pro
Marcus avatar
Marcus
User
Posts: 747
Joined: 23-Apr-2004
# Posted on: 01-Jan-2005 18:33:34   

Otis wrote:

You mean, it should autocommit unless specified otherwise?

Yes I guess so..., but not if there is already a transaction in progress.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 01-Jan-2005 20:24:48   

hmmm. but that makes it confusing, at least I think it does: it's always automatic unless some situation is going on, which can lead to bugs due to assumptions which turned out to be wrong simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Marcus avatar
Marcus
User
Posts: 747
Joined: 23-Apr-2004
# Posted on: 02-Jan-2005 02:02:39   

Otis wrote:

hmmm. but that makes it confusing, at least I think it does: it's always automatic unless some situation is going on, which can lead to bugs due to assumptions which turned out to be wrong simple_smile

mmm... but isn't this how Adapter.SaveEntity works? Either I am controlling the transaction or LLBLGen is controlling it...

When you call Adapter.SaveEntity, if a transaction is not already in progress, it starts a new one. After all the recursive saves it only commits/rollsback the transaction if it was was not already in progress before the call to SaveEntity...

I just thought that UnitOfWork might behave in the same way, but it doesn't. When you return from a UnitOfWork, I am now controlling a transaction that I did not start...

"uow.Commit(adapter, !adapter.IsTransactionInProgress);" provides this same functionality as Save.Entity... I think... simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 02-Jan-2005 12:24:55   

No, there's a difference. The only object which controls a transaction is the DataAccessAdapter. So a unitofwork can't contain a transaction object, a passed on adapter does. As you pass in a DataAccessAdapter (and not calling a method on it), it might be that it already controls a transaction and then you have two options: commit it or not. Also, perhaps you want to keep the transaction open which is started by the unitofwork.

There are 2 overloads of UnitOfWork2.Commit: one which does and which which doesn't accept a flag for autocommit. The default behavior for the one which doesn't accept an autocommit flag is that it doesn't do an autocommit. This is done because you pass in a dataaccessadapter, and you have to commit the transaction yourself.

Frans Bouma | Lead developer LLBLGen Pro
Marcus avatar
Marcus
User
Posts: 747
Joined: 23-Apr-2004
# Posted on: 02-Jan-2005 13:32:47   

Otis wrote:

No, there's a difference. The only object which controls a transaction is the DataAccessAdapter. So a unitofwork can't contain a transaction object, a passed on adapter does. As you pass in a DataAccessAdapter (and not calling a method on it), it might be that it already controls a transaction and then you have two options: commit it or not. Also, perhaps you want to keep the transaction open which is started by the unitofwork.

There are 2 overloads of UnitOfWork2.Commit: one which does and which which doesn't accept a flag for autocommit. The default behavior for the one which doesn't accept an autocommit flag is that it doesn't do an autocommit. This is done because you pass in a dataaccessadapter, and you have to commit the transaction yourself.

But this is my whole point stuck_out_tongue_winking_eye

Say: The DataAccessAdapter DOES NOT have a transaction in progress. It is passed to UnitOfWork.Commit. UnitOfWork starts a transaction on the DataAccessAdapter. UnitOfWork calls Save(s) / Delete(s) on DataAccessAdapter. UnitOfWork returns. Default behaviour is "not" to autocommit. DataAccessAdapter now has an "open" transaction.

The user is now responsible for committing a transaction he did not explicity start. I dont know of any other area of LLBLGen where there is a similar pending transaction as a result of a call to core method other than adapter.StartTransaction... simple_smile

On the other hand say: The DataAccessAdapter DOES have a transaction in progress. It is passed to UnitOfWork.Commit. UnitOfWork DOES NOT start another transaction as one in already in progress. UnitOfWork calls Save(s) / Delete(s) on DataAccessAdapter. UnitOfWork returns. Default behaviour is "not" to autocommit. DataAccessAdapter now has an "open" transaction. (as expected)

In this instance I would expect DataAccessAdapter to have an open transaction as I was the one who started it... If I had called UnitOfWork.Commit with autoCommit = true, then my entire transaction would have committed which is more than likely not what I would want...

I just think that given there is no support for nested transactions, I like the way LLBLGen is clever enough on the DataAccessAdapter Save methods to work around this problem. The starting and committing of the internal transaction is "hidden" from the user. The Save method returns leaving my transaction state "unchanged".

But I simply noticed that with UnitOfWork, the internal transaction (abeit not "owned" by UnitOfWork) does change state (by default) after the call. And this is something that caused me a bug until I realised that I needed to call it specifying the autoCommit flag (using uow.Commit(adapter, !adapter.IsTransactionInProgress)wink in order to maintain transaction state after the call returns.

Maybe it's just me simple_smile , but I think the default behaviour is far more confusion than having transaction state "unchanged" after the Commit methods returns... stuck_out_tongue_winking_eye

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 02-Jan-2005 16:14:26   

Good point.

there is one problem though: if I change the default behavior, people who build on top of that default behavior have a problem with their code. So've to come up with a solution to that (or add the breaking change). I'll add to the todo list that this default behavior should be changed.

Frans Bouma | Lead developer LLBLGen Pro