我一直在这里和其他地方寻找一段时间,并且无法找到一个很好的答案为什么Linq-TO-SQL与NOLOCK不可能..
每次我搜索如何将with(NOLOCK)提示应用于Linq-To-SQL上下文(应用于1 sql语句)时,人们经常回答强制事务(TransactionScope),并将IsolationLevel设置为ReadUncommitted。好吧 - 他们很少告诉这导致连接打开一个事务(我也读过某个地方必须确保手动关闭)。
在我的应用程序中按原样使用ReadUncommitted,实际上并不是那么好。现在我已经在彼此之间使用了相同连接的上下文语句。像:
using( var ctx1 = new Context()) {
... some code here ...
using( var ctx2 = new Context()) {
... some code here ...
using( var ctx3 = new Context()) {
... some code here ...
}
... some code here ...
}
... some code here ...
}
总执行时间为1秒且同时有多个用户,更改隔离级别将导致上下文等待彼此释放连接,因为正在使用连接池中的所有连接。
因此,改变为“nolock”的原因之一是避免死锁(现在我们每天有1个客户死锁)。上面的结果只是另一种僵局,实际上并没有解决我的问题。
所以我知道我能做的是:
但我的问题是:
我的想法是:
答案 0 :(得分:2)
1:LINQ-to-SQL确实不允许你指出像NOLOCK
这样的提示;但 可以编写自己的TSQL,并使用ExecuteQuery<T>
等
2:坦率地说,以优雅的方式解决会非常复杂;并且很有可能你会不恰当地使用它。例如,在“死锁”场景中,我会下注实际上你应该使用UPDLOCK
(在第一次阅读期间),以确保第一次读取采用写入锁;这可以防止后来的第二个查询获得读取锁,因此通常会阻塞而不是死锁
3:使用连接不一定是一个大问题(虽然请注意new Context()
不会通常共享连接;要共享连接,您将使用{{1} })。如果看到这个问题,有三种可能的解决方案(如果我们排除“使用带有提示支持的ORM”):
new Context(connection)
- 它可以是连接级别事务)来指定隔离级别TransactionScope
一些事务创建代码子类化,以控制它在内部创建的事务的隔离级别。