.NET TransactionScope and flushing - correct behaviour

71 views
Skip to first unread message

MixMasta

unread,
Aug 26, 2010, 2:12:53 AM8/26/10
to nhusers
I am using a .NET transaction scope and running the following to
verify transaction commits/rollbacks
Using 2.1 nhibernate talking to SQL server db.

var b1 = new Person {Email = "a...@a.com", Username = "art"};
using (var session = NHibernateSession.CurrentFor("MyDatabase"))
{
session.Save(b1);
session.Flush();
}
//Writes b1 away to database

using (var tx = new TransactionScope())
{
using (var session = NHibernateSession.CurrentFor("MyDatabase"))
{
var b2 = (Person)session.Load(typeof(Person), b1.Id);
b2.Username = "art1234";
session.Flush();
}
tx.Complete();
}

using (var session = NHibernateSession.CurrentFor("MyDatabase"))
{
var b3 = (Person)session.Load(typeof(Person), b1.Id);
Assert.IsTrue(b3.Username == "art");
}


If I leave the session.Flush() uncommented the transaction commits
even if I have the tx.Complete() commented out - I was expecting the
transaction scope to decide whether to commit those changes. If I
comment out session.Flush() and don't set tx.Complete() then the
transaction rolls back as expected.

My guess is that session.Flush creates its own implicit transaction
and commits it and ignores the current .NET transaction scope.

Thanks

Jason Dentler

unread,
Aug 26, 2010, 6:52:19 AM8/26/10
to nhu...@googlegroups.com
First, you must use an NHibernate transaction for all database interaction. TransactionScope is not a substitute. 

Second, TransactionScope should only be used when you need to coordinate more than one resource. Even then, you should still use an NHibernate transaction as well.

Third, TransactionScope allows each resource to vote whether the transaction should be rolled back or committed. If everyone votes commit, then it's committed. When you use a real NH transaction, you can control which way NHibernate will vote.


--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To post to this group, send email to nhu...@googlegroups.com.
To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.


Jason Dentler

unread,
Aug 26, 2010, 6:55:46 AM8/26/10
to nhu...@googlegroups.com
By the way, calling Session.Flush with "flush on commit" is a good indication that you are doing something wrong. You should be using an NHibernate transaction instead.

MixMasta

unread,
Aug 26, 2010, 7:19:50 AM8/26/10
to nhusers
I don't have the option of using a nhibernate transaction in my
scenario.
NHibernate has support for transactionscope so it should enlist in the
transaction.

On Aug 26, 12:52 pm, Jason Dentler <jasondent...@gmail.com> wrote:
> First, you must use an NHibernate transaction for all database interaction.
> TransactionScope is not a substitute.
>
> Second, TransactionScope should only be used when you need to coordinate
> more than one resource. Even then, you should still use an NHibernate
> transaction as well.
>
> Third, TransactionScope allows each resource to vote whether the transaction
> should be rolled back or committed. If everyone votes commit, then it's
> committed. When you use a real NH transaction, you can control which way
> NHibernate will vote.
>
> > nhusers+u...@googlegroups.com<nhusers%2Bunsu...@googlegroups.com>
> > .

MixMasta

unread,
Aug 26, 2010, 7:31:28 AM8/26/10
to nhusers
Opening a Nhibernate session within a TransactionScope should and does
have actions performed under that session being enlisted in the
current ambient transaction.

I usually don't call session.flush but did in this case and
experienced this behaviour. Not calling trx.complete() should rollback
the transaction even if session.flush() is invoked.



On Aug 26, 12:55 pm, Jason Dentler <jasondent...@gmail.com> wrote:
> By the way, calling Session.Flush with "flush on commit" is a good
> indication that you are doing something wrong. You should be using an
> NHibernate transaction instead.
>
> On Thu, Aug 26, 2010 at 5:52 AM, Jason Dentler <jasondent...@gmail.com>wrote:
>
> > First, you must use an NHibernate transaction for all database interaction.
> > TransactionScope is not a substitute.
>
> > Second, TransactionScope should only be used when you need to coordinate
> > more than one resource. Even then, you should still use an NHibernate
> > transaction as well.
>
> > Third, TransactionScope allows each resource to vote whether the
> > transaction should be rolled back or committed. If everyone votes commit,
> > then it's committed. When you use a real NH transaction, you can control
> > which way NHibernate will vote.
>
> >> nhusers+u...@googlegroups.com<nhusers%2Bunsu...@googlegroups.com>
> >> .

John Davidson

unread,
Aug 26, 2010, 7:47:57 AM8/26/10
to nhu...@googlegroups.com
Using TransactionScope in your example may cause some form of database interaction, but it will not be correct unless you follow the rules as specified by Jason.

John Davidson

To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.

Diego Mijelshon

unread,
Aug 26, 2010, 9:07:36 AM8/26/10
to nhu...@googlegroups.com
NH will enlist its transactions in the transactionscope, but they are not optional.
 
    Diego


To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages