为什么SQL Server隔离级别使用EF TransactionScope

时间:2017-10-25 14:49:09

标签: sql-server entity-framework transactionscope isolation-level

我遇到使用Entity Framework TransactionScopes的问题。

在阅读文档并查看多个示例和建议后,我在Web应用程序中的许多查询中实现了事务范围。我在这里遇到的问题与隔离级别有关。我希望TransactionScope中的每个查询都是ReadUncommited,但由于某种原因,只有第一个查询需要隔离级别(READ UNCOMMITED),但所有后续查询都恢复为READ COMMITED。这些查询读取了大量数据,我不介意脏读。

这是我的EF TransactionScope和Context(非常基本):

    var transactionOptions = new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted };
    using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions, TransactionScopeAsyncFlowOption.Enabled))
    {
         using (var db = new Context())
         {
               //db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
               //var SessionID = await db.Database.SqlQuery<short>("SELECT @@SPID").FirstOrDefaultAsync();
               //db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

               //QUERY1
               var list1= await db.Table1.Include(x => x.ExternalProperty).Where(x => x.Created >= sevenDaysAgo).ToListAsync();                    

               //QUERY2
               var list2 = await db.Table1.Include(x => x.ExternalProperty).Where(x => x.Created >= fourteenDaysAgo && x.Created <= eightDaysAgo).ToListAsync();

                //... Doing more stuff here

                transactionScope.Complete();
         }
     }

QUERY 1使用READ UNCOMMITED执行,而由于某种原因,QUERY 2使用READ COMMITED执行。我错过了什么吗?因为在我的理解中,这不应该发生,因为两个查询都使用相同的TransactionScope。

我使用await db.Database.SqlQuery<short>("SELECT @@SPID").FirstOrDefaultAsync()来获取上下文保留的会话ID,以确保使用相同的会话。

我还尝试使用db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");手动设置隔离级别,这导致了相同的行为。

我一直在搜索,几乎所有答案都建议使用上面的代码。例如:THIS ANSWER

为什么会发生这种情况,特别是因为TransactionScope尚未完成?

由于

1 个答案:

答案 0 :(得分:0)

除非有人有更好的答案,否则这就解决了我的问题。

我必须在transactionscope中手动打开和关闭连接,或者命令停止EF上下文在每次查询之间将连接返回到池。

我使用了db.Database.Connection.Open();db.Database.Connection.Close();

请注意,这会在处理上下文之前保持连接处于活动状态。请注意,因为它可能不适合您的场景。