【问题标题】:EF Transactions MSDTC?EF交易MSDTC?
【发布时间】:2011-08-26 14:58:08
【问题描述】:

我在 EF 和事务处理方面遇到了一点问题。

我正在尝试这样做:

using(TransactionScope scope = new TransactionScope())
{
  using(MyEntities model = new MyEntities())
  {
    MyT thing = new MyT{ Value1 = "bla", Value2 = "bla2", Value3 = "foo" };
    model.MyT.AddObject(thing);
    model.SaveChanges();

    thing.Value4 = Service.Call("bar");

    // this call causes an exception in MSDTC
    model.SaveChanges();

    scope.Complete();
  }
}

我这样做的原因是因为我想插入到数据库中,所以 MyT 有一个唯一的 id,我在拨打电话时将其传递给服务,然后从服务中取回一个唯一的 ref 和状态,描述什么在通话期间发生,然后我需要附加到记录中。

我的理解是,在单个事务中,您只能更新一次记录/进行插入调用,但您不能同时执行这两种操作,因为这会由于某种原因造成问题……我曾经有一篇 MSDN 文章解释过无法做到这一点的一些合乎逻辑的原因(可能与锁定有关)。

所以我的问题是如何解决这个问题,但要确保在任何这些调用中发生任何故障时我仍然可以回滚。

【问题讨论】:

  • 您的问题是什么?您发布的代码如何工作?我觉得还可以。
  • 异常是一个 com+ 异常,它简单地读取“com+ 对象中发生异常”就是这样......事件日志中没有任何内容也没有帮助。

标签: c# entity-framework msdtc


【解决方案1】:

当您在事务范围内与数据库建立多个连接时,事务将从本地事务提升为分布式事务,除非您明确使用与数据库的相同连接。

当事务被提升时,它需要 MSDTC 服务来管理事务,所以如果这个服务不可用,它会抛出异常。

类似这样的:

using(TransactionScope scope = new TransactionScope())
{
  using(MyEntities model = new MyEntities())
  {
    model.Connection.Open();
    MyT thing = new MyT{ Value1 = "bla", Value2 = "bla2", Value3 = "foo" };
    model.MyT.AddObject(thing);
    model.SaveChanges();

    thing.Value4 = Service.Call("bar");

    // this call shouldn't cause anymore an exception in MSDTC
    model.SaveChanges();

    scope.Complete();
  }
}

【讨论】:

  • 该服务正在运行,但这会导致进一步的复杂性,因为它决定将给出一个 com+ 异常,在任何日志中几乎没有任何价值,或者在异常中给出 bac。
  • 尽可能避免使用 MSDTC 更有效,尝试显式设置连接以避免它。
  • MSDTC 提升的另一个变体是在事务中多次打开和关闭连接(尽管我认为这已在较新版本的框架中得到修复)。尝试重新使用打开的连接并仅在事务结束时关闭它。
  • 保存更改会自动对连接进行内部打开调用...我认为它也会在每次 savechanges 调用后关闭连接...这意味着您所做的只是将现有代码包装在一个try catch(我已经在做,但为简单起见省略了)
  • 但是你忘了一件事,我打开了连接,因为连接池的关系,当save更改打开的时候,已经打开了,所以关闭的时候并没有关闭它,只是减少打开的计数器,并且仅在该计数器达到零时才关闭它。这样,所有代码都在同一个连接中执行,避免了 MSDTC 来回收事务。
【解决方案2】:

尝试使用事务选项创建事务范围。在事务选项中指定 ReadUncommitted。

http://msdn.microsoft.com/en-us/library/system.transactions.isolationlevel.aspx

http://msdn.microsoft.com/en-us/library/ms149853.aspx

【讨论】:

  • 这并不完全正确,但通过进一步挖掘,我发现问题是由于相关调用的范围,相关代码无法包含在事务中。简单地说,我使用的是自己的事务机制。
猜你喜欢
  • 1970-01-01
  • 2010-11-16
  • 2011-04-27
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多