在使用EF进行基于MSSQL 2008
的查询更新时,存在性能和锁定问题。因此,我设置了 ReadUncommitted 事务隔离级别,希望解决这个问题,就像这样:
之前的代码
using (MyEntities db = new MyEntities())
{
// large dataset
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Probably db lock
db.SaveChanges();
}
之后
using (var scope =
new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
using (MyEntities db = new MyEntities())
{
// large dataset but with NOLOCK
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
for (var item in data)
item.Flag = 0;
// Try avoid db lock
db.SaveChanges();
}
}
我们使用
SQL Profiler
进行跟踪。然而,以下是这些脚本的顺序,
(第一个脚本期望读取未提交的数据。)
审计登录
set transaction isolation level read committed
SP:StmtStarting
SELECT
[Extent1].[ContactId] AS [ContactId],
[Extent1].[MemberId] AS [MemberId],
FROM [dbo].[Contact] AS [Extent1]
WHERE [Extent1].[MemberId] = @p__linq__0
审计登录
set transaction isolation level read uncommitted
虽然我可以重新发送此请求并使其正确排序(以下请求将显示read-uncommitted
,相同的 SPID ),但我想知道为什么它在读取已提交的命令之后发送了read-uncommitted
命令,并且如何使用EF和 TransactionScope进行修复?谢谢。
TransactionScope.Complete()
。这不会影响你所看到的内容,而且你无法回滚一个SELECT
,但这是一个好习惯。另外请注意,如果你没有设置隔离级别,你将得到最后应用于你的池化连接的任何事务级别。如果你从未对隔离级别进行任何操作,则默认为read committed
,否则可能是任何值。请参见此处。 - Jeroen Mostert