【问题标题】:EF Core 3.1 set default IsolationLevel in DbContextEF Core 3.1 在 DbContext 中设置默认 IsolationLevel
【发布时间】:2021-06-04 07:28:12
【问题描述】:

我需要对 DbContext 执行的所有操作都应用相同的 IsolationLevel,所以我不必每次使用时都指定它。 有什么办法吗?

我正在使用 EF Core 3.1 和 SqlServer

更新:经过一些研究和测试,我发现我正在寻找的是将WITH (NOLOCK) 应用于表格。我还尝试将事务范围应用于单个查询并尝试从锁定的表中读取数据,但它不起作用。

这是我使用的代码:

using var transactionScope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted });

// query execution

transactionScope.Complete();

此代码复制自:https://docs.microsoft.com/en-gb/ef/core/saving/transactions,唯一的区别在于 IsolationLevel。

【问题讨论】:

  • 您尝试应用哪个隔离级别?
  • 如果您使用存储过程 - SET ON;在您的存储过程中。如果您使用纯文本,请添加“SET ON;”到你的命令文本。
  • 在这种情况下我不关心数据的可靠性,我想在 Read Uncommitted IsolationLevel 中读取它
  • @yob 我既没有使用存储过程,也没有使用纯文本。我需要在上下文中指定一次,这样上下文执行的每个操作都不需要指定它自己的隔离级别

标签: c# sql-server dbcontext ef-core-3.1 isolation-level


【解决方案1】:

https://stackoverflow.com/a/53082098/12919581

我有这个我能找到的最好的解决方案,即使在我看来还不够好。

它会生成此警告,可能会给未来的更新带来一些问题。

Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerQuerySqlGenerator is an internal API that supports the Entity Framework Core infrastructure and not subject to the same compatibility standards as public APIs. It may be changed or removed without notice in any release.

我没有采用它,但目前这是我能找到的唯一方法,可以在不锁定任何表的情况下读取未提交的数据。

【讨论】:

    【解决方案2】:

    EF Core 是一个可以针对多个数据源运行的 ORM,并非所有数据源都会更改事务隔离级别,因此,在 EF 中,此属性是只读的。如果要为 SQL Server 更改它,则需要在 T-Sql 代码中进行。

    【讨论】:

    • 但是您可以在指定 TransactionScope 的单个操作上执行此操作。我认为在上下文级别也应该可以做到这一点。我错过了什么?
    • 我不相信这在上下文级别是可能的,正如您提到的,您可能希望将上下文操作嵌入到事务范围内以更改默认上下文隔离级别,但不建议这样做.如果您希望数据库中的所有操作都使用完整的数据库默认隔离级别,我只需更改它即可。
    • @Emanuele - 是的,使用 TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions{IsolationLevel = .... 或使用 DbCommandInterceptor (docs.microsoft.com/en-us/dotnet/api/…)
    • 我发现无法将数据库隔离级别更改为 read uncommitted ,这是 sql server 不允许的。所以我必须通过代码来完成。在这一点上我认为我想做的事情做不到
    【解决方案3】:

    您应该在 Dotnet 核心中间件的责任链中执行此操作。 在每个动作执行之前,您可以启动一个事务范围并设置事务隔离级别,并在动作执行后结束它。在此处查看中间件和 dotnet 管道:

    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
           app.Use(async (context, next) =>
           {
               //begin your transaction scope.
               await next.Invoke();
               //finalize the corresponding scope.
           });
        }
     }
    

    这种模式与工作单元实现非常相似。

    【讨论】:

    • 这个不行,我发现必须为每个查询设置隔离级别,不能在启动级别完成。 github.com/dotnet/SqlClient/issues/96
    • 它不在启动级别执行:|它就在 startup.cs 类中!它将在每个请求上下文中执行:)
    • 是的,但它只会应用于第一个查询。
    猜你喜欢
    • 2021-01-21
    • 2019-07-02
    • 2021-05-01
    • 2020-07-01
    • 2022-01-09
    • 2021-03-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    相关资源
    最近更新 更多