.net - 如何全局更改所有 Entity Framework 事务的 IsolationLevel

标签 .net entity-framework

我正在为我的下一个新应用评估 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 不是一个好主意。我这样说有错吗?

对于 Serialized 和 SQL Server(与 Oracle 相比),插入简单的看似无害的读取可能会导致转换锁死锁。

来自 EF 常见问题解答: “如果您需要让读取器不阻止写入器并且写入器不阻止读取器,建议您使用 READ COMMITTED 事务,并使用 READ COMMITTED SNAPSHOT ISOLATION。”

我不明白为什么 EF 默认为可串行化,并且使更改默认隔离级别变得如此困难 - 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();
            }
        }
    }
    ...

如您所见,在未指定 IsolationLevel 的情况下调用了 BeginTransaction。在底层,它使用 IsolationLevel.Unspecified 创建提供者特定的事务。未指定的隔离级别应导致数据库服务器/驱动程序采用默认隔离级别。在 SQL Server 中,默认隔离级别是 READ COMMITED,因此我希望它应该使用它,但我尚未测试它。

如果您想全局更改隔离级别,您可以在从 ObjectContext 派生的类中重写 SaveChanges 并将 base.SaveChanges() 包装在自定义TransactionScope

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

相关文章:

c# - ForEach lambda 表达式可以有可选的返回类型吗

entity-framework - 如何详细记录我的实体错误

c# - 使用 Entity Framework 模型键入安全 key

entity-framework - 如何在 Entity Framework 模型中编写递归查询代码?

c# - 与 Entity Framework Core 2.0 的一对零关系

.net - 如何在Windows Azure平台上开发Facebook应用程序?

c# - 如何使用 C# 访问共享点数据?

.net - 如何为具有多个项目的.net解决方案执行MSBuild.SonarQube.Runner?

c# - 同一语句中的一些粗体和一些简单的词

entity-framework - 涉及复杂对象的 Entity Framework 的 Linq 表达式构建