我正在为我的下一个新应用评估EF。

如何在应用程序中全局更改所有EF事务的IsolationLevel?
例如:假设我要使用“读取提交的快照”。

尽管我明确需要TransactionScope时也可以指定IsolationLevel(请参见下面的代码),但必须将每个EF保存操作封装在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不是一个好主意。我说错了吗?

使用Serializable和SQL Server(与Oracle相反),插入简单的无辜外观读取可能会导致转换锁死锁。

从EF常见问题解答:
“建议您使用READ COMMITTED事务,并在需要读取器不阻止写入者且写入器不阻止读取器的情况下使用READ COMMITTED SNAPSHOT ISOLATION。”

我不明白为什么EF默认设置为Serializable,并且很难更改默认的隔离级别-SQL Server(与Oracle的多版本相反)默认设置为悲观的并发模型。配置选项应该很容易实现-还是我在这里错过了一些东西?

最佳答案

我几乎可以确定默认的EF事务隔离级别是基于使用的数据库提供程序的。 SaveChanges执行以下代码:

    ...
    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,因此我希望它可以使用它,但我尚未对其进行测试。

如果要全局更改隔离级别,则可以在派生自SaveChanges的类中覆盖ObjectContext并将base.SaveChanges()包装在自定义TransactionScope中。

关于.net - 如何全局更改所有 Entity Framework 事务的隔离级别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5126602/

10-11 02:02