ASP.Net MVC 5 和 SQL 事务隔离级别
Posted
技术标签:
【中文标题】ASP.Net MVC 5 和 SQL 事务隔离级别【英文标题】:ASP.Net MVC 5 and SQL Transaction Isolation Levels 【发布时间】:2015-08-17 02:48:23 【问题描述】:在为数据库创建前端时遇到问题。我从数据库中的 EF6 Code First 开始。我创建了控制器并在创建页面上运行测试,但遇到了一个大问题。它给了我以下错误:
System.Data.SqlClient.SqlException: Transaction failed in database 'DB' because the statement was run under snapshot isolation but the transaction did not start in snapshot isolation. You cannot change the isolation level of the transaction to snapshot after the transaction has started unless the transaction was originally started under snapshot isolation level.
显示的另一件事是来自控制器的代码:
if (ModelState.IsValid)
db.Characters.Add(character);
await db.SaveChangesAsync();
return RedirectToAction("Index");
它突出显示了等待 db.SaveChangesAsync();作为错误线。所以现在我很困惑在哪里可以更改 MVC 代码中的事务级别。是 Web.config、为数据库创建的模型还是控制器?我知道我必须使用 TransactionScope 来更改它。 更容易将默认事务范围更改为数据库的设置。只是不确定在哪里进行更改?
【问题讨论】:
db
在哪里被实例化,你应该在使用db
上下文时使用using
语句。
你应该在你的控制器里放什么?
所以我应该把它放在我拥有的控制器中: private DBModel db = new DBModel(); ?这应该在新的 DBModel 中使用(使用 TransactionScopeOption.IsolationLevel.Snapshot )?
不要将DBModel
设为私有,请参阅以下文章msdn.microsoft.com/en-us/data/jj729737.aspx中的Lifetime
部分
【参考方案1】:
在EF
上下文的构造函数中,您可以调用以下内容,传入您想要的IsolationLevel
_ContextTransaction = Database.BeginTransaction(isolationLevel)
然后通过覆盖上下文中的SaveChangesAsync
,您可以提交事务
public override Task<int> SaveChangesAsync()
var result = base.SaveChangesAsync();
_ContextTransaction.Commit();
请注意,对于其他 Saving
方法,您还需要 Commit
事务,并且您还可以考虑在使用 BeginTransaction(isolationLevel)
开始新事务之前测试上下文是否是另一个事务的一部分
要检查当前交易,您可以使用System.Transactions.Transaction.Current
【讨论】:
我只是想澄清一下,我的 EF 上下文的构造函数是: public partial class DBModel : DbContext public DBModel() : base("name=DBModel") 我添加了 _ContextTransaction = Database.BeginTransaction(isolationLevel);到 base("name=DBModel") 之后的大括号,但它不喜欢 _ContextTransaction 和isolationLevel,它希望我添加它们在模型中的一些版本。 您需要在类中定义一个私有变量_ContextTransaction
,即private DbContextTransaction _ContextTransaction;
。 isolationLevel
应该是您要使用的“IsolationLevel”枚举中的选项
好吧,让 DBA 删除数据库上的快照并没有帮助。从那以后他们就把它放回去了。将私有 DBContextTransaction _ContextTransaction 放入 DBModel.cs 中,然后添加 _ContextTransaction = Database.BeginTransaction(isolationLevel Snapshot) 导致 = 符号成为问题,同时 .BeginTransaction 说它是一种像字段一样使用的方法。将异步代码从控制器中取出会导致相同的事务问题。我们没有想法。以上是关于ASP.Net MVC 5 和 SQL 事务隔离级别的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET MVC 5使用Filter过滤Action参数防止sql注入