实体框架核心读取未提交的问题



我们的一个内部应用程序上有一个相当重的模块,它使用 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;
}

这会导致以下错误消息:

无效操作异常:警告作为警告的错误异常 'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning': 检测到环境事务。实体框架核心 不支持环境事务。看 http://go.microsoft.com/fwlink/?LinkId=800142 为了抑制这一点 例外使用 DbContextOptionsBuilder.ConfigureWarnings API。 配置警告可以在覆盖 DbContext.OnConfiguration方法或在 应用程序服务提供商。

因此,我试图抑制警告:

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

这会导致此错误消息:

不支持异常:在环境事务中登记不是 支持。

所以现在我有点迷茫,我可以看到其他人已经在官方问题跟踪器上记录了这个问题,但我不明白实际问题是什么,以及如何强制这个特定模块对数据进行"脏"读取,以阻止锁发生。

首先,你得到的建议有点过时了。自 SQL Server 2005 以来,数据库快照已启用无锁定查询。这应该是默认设置,但我想它可能已被关闭。若要进一步调查,请参阅相关文档。无论何时何方,只要启用此功能,就不必担心查询会创建锁。

其次,EF Core 中存在一个 bug,该 bug 当前阻止你拥有的代码正常工作。但是,它已经被修复,但它仍在上游(即它尚未推出)。基本上,你现在不能这样做,但你很快就能做到。如果第一个解决方案不起作用,我会说等待。

最后,假设第一个解决方案由于某种原因不适合您,并且您绝对不能等待修复程序推出,您始终可以为使用 NOLOCK 的查询创建一个或多个存储过程。这当然是一个更手动的工作,所以我首先从你最重的查询开始。在查询之前和之后分析查询,您还可以考虑进行一些负载测试,以确保您确实为自己购买了一些东西。

最新更新