我们的内部应用程序中有一个非常繁重的模块,该模块使用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。当然,这是一种手动操作,因此,我将首先从您最繁琐的查询开始。前后对查询进行概要分析,您也可以考虑进行一些负载测试,以确保您确实为自己买了一些东西。