I think TransactionManager needs some improvement to make this scenario work well.
I think it should have a Commit() method that you always call at the end of your using block.
Internal to TransactionManager, the Commit() method would actually do nothing, unless the reference count is 1, in which case it would really commit the transaction.
If the reference count hits 0 without that last Commit() call, the transaction would roll back.
If you are willing to work with me on this, we can do these changes and make the class better. Does that sound good?
OK, so this is untested, but seems like a good overall solution:
Why don't you give this a try (drop this code in place of the TransactionManager you have now) and see if it works.
You should now be able to write DAL code like this:
using (var tr = TransactionManager.GetManager<...>(...))
{
// do stuff here
tr.Commit();
}
The Commit() call won't actually do anything unless it is in the top-level using block, so it is safe to put in every using block.
The actual commit/rollback won't occur until the TransactionManager is disposed as it leaves the last using block.
Let me know if this works, or if you can see a better/different solution.
using (var tr = TransactionManager.GetManager<...>(...))
{
// do stuff here
tr.Commit();
}
Hi Rocky
I'm using CSLA.NET 4 and ADO transactions. I found two different ways of commiting and can't find out which is the good one:
using (var ctx = TransactionManager<SqlConnection, SqlTransaction>.GetManager(Database.MyConnection, false))
{
using (var cmd = new SqlCommand("AddStuff", ctx.Connection))
{
cmd.Transaction = ctx.Transaction;
...
}
...
ctx.Commit(); // (A)
ctx.Transaction.Commit(); // (B)
}
In your above example you use (A).
(B) seems to refer to the SqlTransaction. Does it also trigger the TransactionManager logic?
What's the difference of using (A) or (B)?
You should use (A).
If you commit directly on the IDbTransaction object itself you might be committing before some higher level code is complete.
If you commit on the TransactionContext object, it just records that you want to commit. A higher level bit of code could still cause a rollback - ultimately the commit/rollback decision isn't made until the highest level using block is closed and the context object is disposed - that's the only point at which you know that all your code has had a chance to "vote" on commit/rollback.
They may be using Oracle, in which case TransactionScope won't work (without triggering the DTC), in which case the best option is to manually use ADO.NET transactions.
Of course this is all guesswork since the poster hasn't responded :)
Copyright (c) Marimer LLC