Transaction Isolation Levels using System.Transactions.

Transaction Isolation Levels using System.Transactions.

Old forum URL: forums.lhotka.net/forums/t/560.aspx


karl posted on Friday, July 07, 2006

When using ADO.NET transactions in Data Access Code I can set the Isolation Level of the transaction as follows:-

Private Overloads Sub DataPortal_Fetch(ByVal criteria As Criteria)

Using cn As New SqlConnection(Common.Connections.MyConnection)

cn.Open()

Using tr As SqlTransaction = cn.BeginTransaction(IsolationLevel.ReadCommitted)

Now, if I altered the code to use System.Transactions (as Rocky recommends in his new book) I would write the code as follows:-

<Transactional(TransactionalTypes.TransactionScope)> _

Protected Overrides Sub DataPortal_Insert()

Using cn As New SqlConnection(Database.PTrackerConnection)

cn.Open()

Using cm As SqlCommand = cn.CreateCommand

etc.

How do I set the Transaction Isolation level of the system.transaction, as I did with the ADO.NET transaction?

 

msk replied on Friday, July 07, 2006

This is just a guess but perhaps by referencing the System.Transactions assembly from your class library and adding the following code to your DataPortal_XYZ methods:

System.Transactions.Transaction.Current.IsolationLevel = IsolationLevel.ReadCommitted

karl replied on Friday, July 07, 2006

Martin,

That was the first thing that I tried, but the Property 'IsolationLevel' is Readonly!!!!!

Thanks for making the effort though. 

msk replied on Friday, July 07, 2006

Kark, I've just had a look in the documentation for transactionscope - RTFM ;)  It looks like when you create a transaction scope you can specify options - timeout and isolationlevel.  You would have to create another transaction scope in your DataPortal_XYZ.  If I'm reading it correctly, there are also the Required, Requires New, ... options - they look to work like the old MTS/COM+ option.  You should be able to make the new transactionscope join the ambient transactionscope but with a downgraded isolationlevel. 

karl replied on Friday, July 07, 2006

Kartin,

Thanks for your reply. Will creating a new transaction scope automatically particapate in the current ambient transaction. For example would the following work :-

<Transactional(TransactionalTypes.TransactionScope)> _

Protected Overrides Sub DataPortal_Update()

 

Dim tranop As New System.Transactions.TransactionOptions

tranop.IsolationLevel = Transactions.IsolationLevel.Snapshot

Dim tso As New System.Transactions.TransactionScopeOption

Dim mytransscope As New System.Transactions.TransactionScope(tso, tranop)

 

Me.RaiseListChangedEvents = False

Using cn As New SqlConnection(Database.PTrackerConnection)

etc

Thanks in advance, Karl.

 

msk replied on Monday, July 10, 2006

I'm not sure Karl.  You'll have to try it yourself, I have real work to do ;)  It looks to be on the right lines but I you may have missed a bit.  Try this:

Dim tranOpt As New TransactionOptions

tranOpt.IsolationLevel = IsolationLevel.Snapshot

Using tscope As New TransactionScope(TransactionScopeOption.RequiresNew, tranOpt)

'data access code in here

End Using

 

karl replied on Monday, July 10, 2006

It looks like you do need the TransactionScopeOption.RequiresNew statement otherwise you get an error when it tries to change the isolation level of the current ambient transaction. If you don't use the using statement you get a  system.transactions.transactionscope.dispose error when it tries to change the isolation level of the current ambient transaction, the MSDN documentation does mention this.

I guess that you would also need a tscope.complete statement just before the end of using statement, otherwise the trans wouldn't commit. I presume Rocky does something similar within the framework?

Although I appreciate your help Martin, I think we have drifted away from the original question! What I really want to do is create attributes to specify the isolation level on the the DataPortal Methods, example :-

<Transactional(TransactionalTypes.TransactionScope_ReadUncommited)> _

Protected Overrides Sub DataPortal_Update()

or

 

<Transactional(TransactionalTypes.TransactionScope_Chaos)> _

Protected Overrides Sub DataPortal_Update()

I guess I will need to add my own Transaction Scope types to the framework, for example Csla.TransactionTypes.TransactionScope_ReadUncommitted, I would then set the isolation within these. I wonder if anyone has read the section in the book on Transactions - is what I suggest possible?

 

 

 

msk replied on Monday, July 10, 2006

I agree, doing it with attributes would be a good idea - after all one of the aims of the framework is to reduce the amount of plumbing code needed. 

Not sure if it's the ideal way but the TransactionalDataPortal code could be changed.  It looks like this now:

Public Function Fetch( _

ByVal objectType As Type, _

ByVal criteria As Object, _

ByVal context As Server.DataPortalContext) As Server.DataPortalResult _

Implements Server.IDataPortalServer.Fetch

Dim result As DataPortalResult

Using tr As New TransactionScope

Dim portal As New SimpleDataPortal

result = portal.Fetch(objectType, criteria, context)

tr.Complete()

End Using

Return result

End Function

This could be changed to look at the attribute and  include the options based on what isolation level was asked for. 

 

Copyright (c) Marimer LLC