I am evaluating EF for my next new apps.
How can I globally change the IsolationLevel of all EF transactions in an application?
Ex: Suppose I want to use “Read Committed Snapshot”.
While it is OK to specify the IsolationLevel when I explicitely need a TransactionScope anyway (see code below) it would be ugly having to encapsulate every EF save operation in a TransactionScope.
'OK
Using tsc As New TransactionScope(TransactionScopeOption.RequiresNew, TransactionOption.ReadCommitted)
UpdateShoppingCart
EnqueueNewOrder
SendConfirmationEmail
tsc.Complete
End Using
'Is this really the only way to avoid Serializable?
Using tsc As New TransactionScope(TransactionScopeOption.RequiresNew, TransactionOption.ReadCommitted)
_ctx.SaveChanges()
tsc.Complete
End Using
Class TransactionOption
Public Shared ReadOnly ReadCommitted As New TransactionOptions() With {
.IsolationLevel = IsolationLevel.ReadCommitted,
.Timeout = TransactionManager.DefaultTimeout
}
End Class
I assume mixing IsolationLevles is not a good idea. Am I wrong with that?
With Serializable and SQL Server (in contrast to Oracle) inserting a simple innocent looking read may cause a conversion lock deadlock.
From the EF FAQ:
“It is recommended that you use READ COMMITTED transactions, and use READ COMMITTED SNAPSHOT ISOLATION if you need to have readers not block writers and writers not block readers.”
I do not understand why EF defaults to Serializable and makes it so difficult to change the default isolation level – with SQL Server (in contrast to Oracle’s multi-versioning) defaulting to a pessimistic concurrency model. A configuration option should be very easy to implement – or am I missing something here?
I’m almost sure that default EF transaction isolation level is based on used database provider.
SaveChangesexecutes this code:As you can see
BeginTransactionis called withoutIsolationLevelspecified. Under the hood it creates provider specific transaction withIsolationLevel.Unspecified. Unspecified isolation level should result in default isolation level for database server / driver. In SQL Server default isolation level isREAD COMMITEDso I expect it should use it but I haven’t tested it yet.If you want to globally change isolation level you can override
SaveChangesin your class derived fromObjectContextand wrapbase.SaveChanges()in customTransactionScope.