如何防止死锁以及如何在实体框架中设置隔离级别
本文关键字:框架 设置 隔离级 实体 何防止 死锁 | 更新日期: 2023-09-27 18:18:56
我的应用程序有很多死锁(asp.net mvc,实体框架代码第一)
所以我找到了一些关于死锁的博客文章。有一篇博客文章建议使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
dbcontext.database.executesqlcommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;")
我在sql server上执行这个sql命令,然后检查事务隔离级别,读取为未提交。
但是当我使用ef和linq并在运行"set transaction"的行之后设置断点并返回SQL检查事务级别时,它仍然是读提交的,并且再次我有这么多死块。
我发现的另一个解决方案是在这里,建议使用作用域来设置隔离级别
using (var scope = new TransactionScope(TransactionScopeOption.Required, new
TransactionOptions { IsolationLevel= IsolationLevel.Snapshot }))
{
// do something with EF here
scope.Complete();
}
但是在使用每个请求上下文时是否可以使用作用域?
第一个问题是,为什么在通过dbcontext将事务级别设置为读取未提交后,它仍然是读取提交的?
第二个问题是,在这篇博文中提到设置隔离级别是每个上下文,这是否意味着在处理dbcontext后隔离级别回到read committed?
和最后我使用的是ef代码第一个v6,并使用统一使dbcontext每个请求我有什么其他的选择,所以我避免这么多的死块正在发生?
首先,检查死锁是从哪里来的。这将帮助你找到你的问题所在——你需要修复的地方。
有时候orm在复杂的逻辑上有问题。一种选择是为实体框架提供一个存储过程,用于读取和写入更多数据密集型表。
在您的控制器或存储库层中,您可以执行这样的存储过程:
Context.Database.SqlQuery<MyEntityType>("Exec mySpName '@p0, '@p1", param1, param2);
对于不返回数据的过程,也可以使用Database.ExecuteSqlCommand
。
存储过程通常通过执行计划缓存获得性能提升。
使用Read Uncommitted
不是灵丹妙药,但是如果您真的不关心脏读可能返回的坏数据,那么您可以通过设置序列化或使用NoLock
提示来保证您的存储过程不会占用读锁。