如何在全球所有实体框架的交易变化的IsolationLevel [英] How to globally change IsolationLevel of all Entity Framework transactions
问题描述
我评估EF为我的下一个新的应用程序。
I am evaluating EF for my next new apps.
我怎样才能改变在全球所有EF交易的IsolationLevel在应用程序? 例:假设我想用读提交快照
How can I globally change the IsolationLevel of all EF transactions in an application? Ex: Suppose I want to use "Read Committed Snapshot".
虽然它是确定指定的IsolationLevel时,我明确地反正需要一个TransactionScope(见下文code),这将是丑陋的具有封装每个EF保存操作在一个TransactionScope。
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
我认为混合IsolationLevles是不是一个好主意。难道我错了吗?
I assume mixing IsolationLevles is not a good idea. Am I wrong with that?
通过序列化和SQL Server(相对于甲骨文)将一个简单的无辜样子读取可能导致转换锁死锁。
With Serializable and SQL Server (in contrast to Oracle) inserting a simple innocent looking read may cause a conversion lock deadlock.
从EF常见问题解答: 我们建议您使用读提交的事务,并使用READ COMMITTED快照隔离,如果你需要有读者不会阻止作家和作家不会阻止读者。的
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."
我不明白为什么EF默认为可序列化,并使得它如此难以改变默认的隔离级别 - 与SQL Server(相对于Oracle的多版本),默认为悲观并发模型。配置选项应该是很容易实现 - ?还是我失去了一些东西在这里
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?
推荐答案
我几乎可以肯定,默认EF事务隔离级别是根据使用的数据库供应商。 的SaveChanges
执行此code:
I'm almost sure that default EF transaction isolation level is based on used database provider. SaveChanges
executes this code:
...
try
{
this.EnsureConnection();
flag = true;
Transaction current = Transaction.Current;
bool flag2 = false;
if (connection.CurrentTransaction == null)
{
flag2 = null == this._lastTransaction;
}
using (DbTransaction transaction = null)
{
if (flag2)
{
transaction = connection.BeginTransaction();
}
objectStateEntriesCount = this._adapter.Update(this.ObjectStateManager);
if (transaction != null)
{
transaction.Commit();
}
}
}
...
正如你可以看到的BeginTransaction
被称为无的IsolationLevel
指定。引擎盖下用 IsolationLevel.Unspecified
创建提供商特定的事务。未指定的隔离级别应导致缺省隔离级别的数据库服务器/驱动器。在SQL Server的默认隔离级别为 READ COMMITED
所以我希望它应该使用它,但我还没有测试它。
As you can see BeginTransaction
is called without IsolationLevel
specified. Under the hood it creates provider specific transaction with IsolationLevel.Unspecified
. Unspecified isolation level should result in default isolation level for database server / driver. In SQL Server default isolation level is READ COMMITED
so I expect it should use it but I haven't tested it yet.
如果你想在全球范围内改变隔离级别,你可以覆盖的SaveChanges
在你的类从的ObjectContext
导出并包裹 base.SaveChanges()
在自定义的的TransactionScope
。
If you want to globally change isolation level you can override SaveChanges
in your class derived from ObjectContext
and wrap base.SaveChanges()
in custom TransactionScope
.
这篇关于如何在全球所有实体框架的交易变化的IsolationLevel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!