我们的内部应用程序中有一个非常繁重的模块,该模块使用SignalR检查新通知。我们被告知我们正在数据库上创建锁,并且我们应该对该方法进行未提交的读取。

这不是我以前必须要做的事情,据我所知,EF默认情况下会记录已提交的记录。因此,我将现有查询包装在另一个using语句中,如下所示:

    public IEnumerable<ClientUpdates> GetNotifications(int forPaId)
    {
        using (var transactionScope =
            new TransactionScope(TransactionScopeOption.Required, GetReadUncommitedTransactionOptions()))
        {
            using (var ctx = ContextFactory.CompanyDb)
            {
               // Do stuff

                transactionScope.Complete();

                return objectList;

            }
        }
    }

    private TransactionOptions GetReadUncommitedTransactionOptions()
    {
        var transactionOptions = new TransactionOptions
        {
            IsolationLevel = IsolationLevel.ReadUncommitted
        };

        return transactionOptions;
    }


这将导致以下错误消息:


  InvalidOperationException:警告为警告的错误异常
  'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning':
  已检测到环境事务。实体框架核心
  不支持环境交易。看到
  http://go.microsoft.com/fwlink/?LinkId=800142禁止这样做
  例外使用DbContextOptionsBuilder.ConfigureWarnings API。
  覆盖时可以使用ConfigureWarnings
  DbContext.OnConfiguring方法或在
  应用程序服务提供商。


因此,我试图抑制警告:

services.AddDbContext<DbContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString"));
            options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
        });


导致此错误消息:


  NotSupportedException:不参与环境事务
  支持的。


所以现在我有点迷失了,我可以看到其他人已经在official issue tracker上记录了此问题,但我不知道实际的问题是什么,以及如何强制该特定模块执行“ Dirty”读取数据,以阻止发生锁定。

最佳答案

首先,您得到的建议有些过时。从SQL Server 2005开始,数据库快照已启用查询而没有锁定。这应该是默认设置,但是我想它可能已经关闭了。要进一步调查,请参见relevant documentation。总之,只要启用了此功能,就不必担心查询会创建锁。

其次,EF Core中存在一个错误,该错误当前阻止您拥有的代码正常工作。但是,它已经得到修复,但仍在上游(即尚未推出)。基本上,您现在不能执行此操作,但是很快您将能够执行此操作。如果第一个解决方案不起作用,我会说,等一下。

最后,假设第一个解决方案由于某种原因对您不起作用,并且您绝对等不及要推出此修复程序,则始终可以为使用NOLOCK的查询创建一个或多个存储的proc。当然,这是一种手动操作,因此,我将首先从您最繁琐的查询开始。前后对查询进行概要分析,您也可以考虑进行一些负载测试,以确保您确实为自己买了一些东西。

09-29 23:20