【发布时间】:2014-02-15 07:55:17
【问题描述】:
我怀疑我不完全了解正在发生的事情或发生了什么奇怪的事情。 (我猜第一种情况更可能。)
大局:
- 我正在尝试让 Web 服务异步执行某些操作,因为它们可能很耗时,而且我不希望客户端等待操作完成(只需不时查询结果以查看操作完成)。
- 异步代码包含在事务中 - 万一出现问题,我希望能够回滚任何更改。
- 不幸的是,异步代码的最后一步是调用查询同一数据库的不同服务。
- 尽管将整个事物包装在 Snapshot 事务中,但最后一步还是失败了,因为服务无法从数据库中读取数据。
- 就此而言,虽然正在进行异步操作,但我也无法从数据库中执行简单的 SELECT 语句。
这是我目前用来测试事务的代码示例(首先使用 Entity Framework 5 模型):
using (var transaction = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.RequiresNew, new System.Transactions.TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.Snapshot }))
{
var db = new DataModelContainer();
Log test = new Log();
test.Message = "TEST";
test.Date = DateTime.UtcNow;
test.Details = "asd";
test.Type = "test";
test.StackTrace = "asd";
db.LogSet.Add(test);
db.SaveChanges();
using (var suppressed = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Suppress))
{
var newDb = new DataModelContainer();
var log = newDb.LogSet.ToArray(); //deadlock here... WHY?
}
test = db.LogSet.Where(l => l.Message == "TEST").Single();
db.LogSet.Remove(test);
db.SaveChanges();
transaction.Complete();
}
代码在数据库中创建了一个简单的日志条目(是的,我现在正在玩,所以这些值是垃圾)。我已将 SQL 数据库设置为允许快照隔离,据我所知,仍应允许读取(在此代码中通过使用新的抑制事务和新的DataModelContainer 对这些进行测试)。但是,我无法在被抑制的事务或 SQL Management Studio 中查询 LogSet - 整个表被锁定!
那么……为什么?如果事务范围是这样定义的,为什么会被锁定?我也尝试过其他隔离级别(如ReadUncommited),但仍然无法查询该表。
有人可以解释一下这种行为吗?
【问题讨论】:
-
您的数据库中是否启用了快照隔离? "在事务中使用之前,必须通过设置 ALLOW_SNAPSHOT_ISOLATION ON 数据库选项来启用快照隔离"
-
@Moho 是的。 我已将 SQL 数据库设置为允许快照隔离。无论如何,当使用其他隔离模式(比
Serializable限制更少)时,问题仍然存在,例如ReadUncommited,而且这个甚至不需要在 SQL 服务器上启用快照隔离!
标签: c# sql-server entity-framework transactionscope isolation-level