嵌套事务范围,必需->抑制->必需。

5
内部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();
}
2个回答

5

t3. 在这里没有其他可选择的内容,因为t2的范围是抑制t1而不是创造自己的环境。因此,在最内部的范围内只有t3而没有其他内容。

如果t2是RequireNew,则最内部范围的环境将是t2,因为t3将加入t2。


1
谢谢。我以为它可能会选择最后一个未被抑制的交易。 - Mohnkuchenzentrale
@KroaX 我也曾以为它会使用“t1”,就像我问过的一位非常有经验的同事一样。如果实现方式不同,它确实可以这样做。实际上,在我必须编写自定义的“NoDtcTransactionScope”实现以避免升级到声名狼藉的缓慢MSDTC时,我就是这样做的,只是后来才发现TransactionScope并不是这样实现的,因此我又放弃了这个功能,以尽可能接近原始实现。 - Evgeniy Berezovsky

4
记住:被抑制的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'
  • 保存更改 = 1
  • 添加'Test2'
  • 保存更改 = 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'
  • 保存更改 = 1
  • 添加 'Test2'
  • 保存更改 = 1
  • 添加 'Test3'
  • 保存更改 = 1
  • 计数 = 2
  • 是否有值 'Test1' = 0
  • 是否有值 'Test2' = 1
  • 是否有值 'Test3' = 1

你可以看到:"scope"和"scope3"之间没有关系,因为"scope3"提交了它的更改。

"scope2"也提交了它的更改,因为"scope2"是一个被抑制的作用域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接