c# - 带有 TransactionScope 的 EF6 - IsolationLevel.ReadUncommitted 但首先获得 ReadCommitted

标签 c# sql-server entity-framework-6 transactionscope read-uncommitted

MSSQL 2008 上使用 EF 进行查询更新时存在性能和锁定问题。所以我设置了ReadUncommitted transaction isolationlevel,希望可以这样解决,

之前

using (MyEntities db = new MyEntities())
{
    // large dataset
    var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
    for (var item in data)
          item.Flag = 0;

    // Probably db lock      
    db.SaveChanges(); 
}

之后

using (var scope =
    new TransactionScope(TransactionScopeOption.RequiresNew,
    new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
    using (MyEntities db = new MyEntities())
    {
        // large dataset but with NOLOCK
        var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact;
        for (var item in data)
              item.Flag = 0;

        // Try avoid db lock      
        db.SaveChanges();
    }
}

我们使用SQL 分析器 进行跟踪。但是,按顺序获取这些脚本, (第一个脚本的预期读取未提交。)

审核登录

set transaction isolation level read committed

SP:StmtStarting

SELECT 
 [Extent1].[ContactId] AS [ContactId], 
 [Extent1].[MemberId] AS [MemberId], 
FROM [dbo].[Contact] AS [Extent1]
WHERE [Extent1].[MemberId] = @p__linq__0

审核登录

set transaction isolation level read uncommitted

虽然我可以重新发送这个请求并使其顺序正确(将显示 read-uncommitted 用于以下请求,相同的 SPID),但我想知道为什么它发送了 read-读取提交命令后未提交的命令以及如何使用 EF 和 TransactionScope 修复?谢谢。

最佳答案

我认为这是依赖审计登录事件引起的转移注意力。这显示客户端告诉服务器“设置事务隔离级别读取未提交”的时刻。当连接从池中被挑选出来并重新使用时,它会向您展示稍后的隔离级别。

我通过将 Pooling=false 添加到我的连接字符串来验证这一点。然后,审核登录总是显示事务隔离级别读取已提交。

到目前为止,我在 SQL Profiler 中找不到任何方法来查看 EF 设置事务级别的时刻,也没有任何显式 begin tran

我可以通过读取和记录级别来确认它正在某处设置:

    const string selectIsolationLevel = @"SELECT CASE transaction_isolation_level  WHEN 0 THEN 'Unspecified'  WHEN 1 THEN 'ReadUncommitted'  WHEN 2 THEN 'ReadCommitted'  WHEN 3 THEN 'Repeatable'  WHEN 4 THEN 'Serializable'  WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL  FROM sys.dm_exec_sessions  where session_id = @@SPID";

    static void ReadUncommitted()
    {
        using (var scope =
            new TransactionScope(TransactionScopeOption.RequiresNew,
            new TransactionOptions{ IsolationLevel = IsolationLevel.ReadUncommitted }))
        using (myEntities db = new myEntities())
        {
            Console.WriteLine("Read is about to be performed with isolation level {0}", 
                db.Database.SqlQuery(typeof(string), selectIsolationLevel).Cast<string>().First()
                );
            var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact; // large results but with nolock

            foreach (var item in data)
                item.Flag = 0;

            //Using Nuget package https://www.nuget.org/packages/Serilog.Sinks.Literate
            //logger = new Serilog.LoggerConfiguration().WriteTo.LiterateConsole().CreateLogger();
            //logger.Information("{@scope}", scope);
            //logger.Information("{@scopeCurrentTransaction}", Transaction.Current);
            //logger.Information("{@dbCurrentTransaction}", db.Database.CurrentTransaction);

            //db.Database.ExecuteSqlCommand("-- about to save");
            db.SaveChanges(); // Try avoid db lock
            //db.Database.ExecuteSqlCommand("-- finished save");
            //scope.Complete();
        }
    }

(我说“有点”是因为每个语句都在自己的 session 中运行)

也许这是一个很长的说法,是的,即使您无法通过 Profiler 证明 EF 事务正常工作。

关于c# - 带有 TransactionScope 的 EF6 - IsolationLevel.ReadUncommitted 但首先获得 ReadCommitted,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41759486/

相关文章:

c# - 在 Azure SQL 上保存 Datetimeoffset 不起作用

TFS 联机构建失败 - NuGet 包还原不工作

c# - Entity Framework 在嵌套实体上使用 Where 子句

c# - 使用 MVVM 模式(特别是使用 MVVM Light),如何实现不仅仅是基元的模型?

C# 将对象列表中的对象转换为类型返回左手签名必须是变量错误

c# - 与枚举和公共(public)类(class)混淆 - 为什么它不起作用?

c# - Csharp windows 应用程序 MySql 连接

sql-server - 无法使用 F# TypeProvider 读取日期

mysql - 我怎样才能在where select中返回2行?

mysql - "The provider did not return a ProviderManifestToken string"带有 Entity Framework 的 MySQL