【问题标题】:Nested Transactionscope , Required -> Suppress -> Required嵌套事务范围,必需 -> 禁止 -> 必需
【发布时间】:2012-10-16 13:34:14
【问题描述】:

内部 TransactionScope 将哪个事务作为环境事务?

using ( var t1 = new TransactionScope( TransactionScopeOption.Required ) )
{
    //MyStuff

    using ( var t2 = new TransactionScope( TransactionScopeOption.Suppress) )
    {
        //MyStuff

        using ( var t3 = new TransactionScope( TransactionScopeOption.Required) )
        {
            //Mystuff

            t3.Complete();
        }

        t2.Complete();
    }

    t1.Complete();
}

【问题讨论】:

    标签: c# .net sql-server transactions transactionscope


    【解决方案1】:

    t3。那里没有其他选择,因为 t2 的范围是抑制 t1,而不是创建它自己的环境。因此在最里面的范围内只有 t3 而没有别的。

    如果 t2 是 RequireNew,那么最内层的作用域环境就是 t2,因为 t3 会加入 t2。

    【讨论】:

    • 谢谢。我认为它可能会选择最后一个未抑制的交易
    • @KroaX 我也认为它会使用t1,我也问过一位非常有经验的同事。如果它以不同的方式实施,它可以。事实上,我在自定义 NoDtcTransactionScope 实现中这样做是为了避免升级到臭名昭著的慢 MSDTC,只是得知 TransactionScope 不是这样做的,所以我放弃了这个功能再次,尽可能接近原作。
    【解决方案2】:

    记住:被抑制的 TransactionScope 不需要“完成”

    没有交易。

    例如,您可以在此处执行此操作:

        static void TestMethod()
        {
            using (Model1 ctx = new Model1())
            {
                Console.WriteLine("Count = {0}", ctx.Test.Count());
                Console.WriteLine("Has Value 'Test1' = {0}", ctx.Test.Count(x => x.Value == "Test1"));
                Console.WriteLine("Has Value 'Test2' = {0}", ctx.Test.Count(x => x.Value == "Test2"));
            }
    
            using (Transactions.TransactionScope scope = new Transactions.TransactionScope())
            {
                using (Model1 ctx = new Model1())
                {
                    ctx.Test.Add(new Test { Value = "Test1" });
    
                    Console.WriteLine("Add 'Test1'");
                    Console.WriteLine("SaveChanges = {0}", ctx.SaveChanges());
                }
    
                using (Transactions.TransactionScope scope2 = new Transactions.TransactionScope(Transactions.TransactionScopeOption.Suppress))
                {
                    using (Model1 ctx = new Model1())
                    {
                        ctx.Test.Add(new Test { Value = "Test2" });
    
                        Console.WriteLine("Add 'Test2'");
                        Console.WriteLine("SaveChanges = {0}", ctx.SaveChanges());
                    }
                }
            }
    
            using (Model1 ctx = new Model1())
            {
                Console.WriteLine("Count = {0}", ctx.Test.Count());
                Console.WriteLine("Has Value 'Test1' = {0}", ctx.Test.Count(x => x.Value == "Test1"));
                Console.WriteLine("Has Value 'Test2' = {0}", ctx.Test.Count(x => x.Value == "Test2"));
            }
        }
    

    输出:

    • 计数 = 1
    • 值 'Test1' = 0
    • 值 'Test2' = 0
    • 添加“Test1”
    • SaveChanges = 1
    • 添加“Test2”
    • SaveChanges = 1
    • 计数 = 1
    • 值 'Test1' = 0
    • 值 'Test2' = 1

    这意味着抑制范围内的每个查询都不能通过仅处置范围来回滚。

    但如果你这样做:

        static void TestMethod()
        {
            using (Model1 ctx = new Model1())
            {
                Console.WriteLine("Count = {0}", ctx.Test.Count());
                Console.WriteLine("Has Value 'Test1' = {0}", ctx.Test.Count(x => x.Value == "Test1"));
                Console.WriteLine("Has Value 'Test2' = {0}", ctx.Test.Count(x => x.Value == "Test2"));
                Console.WriteLine("Has Value 'Test3' = {0}", ctx.Test.Count(x => x.Value == "Test3"));
            }
    
            using (Transactions.TransactionScope scope = new Transactions.TransactionScope())
            {
                using (Model1 ctx = new Model1())
                {
                    ctx.Test.Add(new Test { Value = "Test1" });
    
                    Console.WriteLine("Add 'Test1'");
                    Console.WriteLine("SaveChanges = {0}", ctx.SaveChanges());
                }
    
                using (Transactions.TransactionScope scope2 = new Transactions.TransactionScope(Transactions.TransactionScopeOption.Suppress))
                {
                    using (Model1 ctx = new Model1())
                    {
                        ctx.Test.Add(new Test { Value = "Test2" });
    
                        Console.WriteLine("Add 'Test2'");
                        Console.WriteLine("SaveChanges = {0}", ctx.SaveChanges());
                    }
    
                    using (Transactions.TransactionScope scope3 = new Transactions.TransactionScope())
                    {
                        using (Model1 ctx = new Model1())
                        {
                            ctx.Test.Add(new Test { Value = "Test3" });
    
                            Console.WriteLine("Add 'Test3'");
                            Console.WriteLine("SaveChanges = {0}", ctx.SaveChanges());
                        }
    
                        scope3.Complete();
                    }
                }
            }
    
            using (Model1 ctx = new Model1())
            {
                Console.WriteLine("Count = {0}", ctx.Test.Count());
                Console.WriteLine("Has Value 'Test1' = {0}", ctx.Test.Count(x => x.Value == "Test1"));
                Console.WriteLine("Has Value 'Test2' = {0}", ctx.Test.Count(x => x.Value == "Test2"));
                Console.WriteLine("Has Value 'Test3' = {0}", ctx.Test.Count(x => x.Value == "Test3"));
            }
        }
    

    输出:

    • 计数 = 0
    • 值 'Test1' = 0
    • 值 'Test2' = 0
    • 值 'Test3' = 0
    • 添加“Test1”
    • SaveChanges = 1
    • 添加“Test2”
    • SaveChanges = 1
    • 添加“Test3”
    • SaveChanges = 1
    • 计数 = 2
    • 值 'Test1' = 0
    • 值 'Test2' = 1
    • 值 'Test3' = 1

    你可以看到:“scope”和“scope3”之间没有关系,因为“scope3”提交了它的变化。

    “scope2”也提交其更改,因为“scope2”是一个被抑制的范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      相关资源
      最近更新 更多