17

这个问题在这里的一个简单示例中不容易重现,但想知道是否有人有任何经验和提示,这里是问题:

  • 使用实体框架
  • 在应用程序中有很多点,其中 (1) 数据被写入某个实体表,例如客户,(2) 数据被写入历史
  • 这两个动作都使用实体框架,但是,它们使用不同的上下文
  • 这些动作需要同时在一个事务中:即如果一个不能写,另一个不应该写,等等。
  • 我可以用 TransactionScope 包装它们,

像这样:

using (TransactionScope txScope = new TransactionScope()) {
    ...
}

但这给了我:

Microsoft 分布式事务协调器 (MSDTC) 对网络事务禁用。

我们的数据库管理员告诉我MSDTC被选择禁用并且无法安装

因此,我正在尝试使用 MetadataWorkspace 创建自己的 EntityConnection 进行更改,并认为每个上下文都将使用相同的 EntityConnection。然而,事实证明,试图让它工作几乎是不可能的,例如,目前我继续得到上述错误,即使理论上两个上下文都使用 EntityConnection。例如,很难理解实体框架在哪里/为什么需要 MSDTC。

以前有没有人走这条路,有经验或代码示例可以分享?

4

3 回答 3

13

嗯,这个问题很简单。

如果您使用的是 sql server 2008,您应该不会遇到这个问题,因为您有可升级的事务,并且 .NET 知道您使用的是相同的持久性存储(数据库),它不会将其提升到 DTC 并将其作为本地提交。使用 sql server 2008 查看可推广事务。

据我所知,Oracle 正在其驱动程序中工作以支持可升级事务,但我不知道状态,MS oracle 驱动程序不支持它。 http://www.oracle.com/technology/tech/windows/odpnet/col/odp.net_11.1.0.7.20_twp.pdf

如果您使用的驱动程序不支持可升级事务,.NET 就不可能使用本地事务进行两个连接。您应该更改架构或说服数据库管理员安装 MSDTC。

于 2010-03-03T11:07:40.137 回答
1

我在 SQL 2008 实体框架中遇到了类似的问题。

我定义了两个框架(EF1 和 EF2),但使用相同的连接字符串连接到 sql 2008 数据库。

当在两者中使用嵌套的“usings”时,我得到了上面的 MSDTC 错误。例如代码是这样的:

using (TransactionScope dbContext = new TransactionScope())
{
     using (EF1 context = new EF1())
     {
         // do some EF1 db call
         using (EF2 context2 = new EF2())
         {
              // do some EF2 db call
          }
      }
      dbContext.Complete();
}

没有这么简单,因为它被分成了几个方法,但这是“使用”的基本结构。

解决方法是一次只打开一个使用。没有 MTDSC 错误,无需在 db 上打开分布式事务。

using (TransactionScope dbContext = new TransactionScope())
{
     using (EF1 context = new EF1())
     {
         // do some EF1 db call

      }
     using (EF2 context2 = new EF2())
     {
              // do some EF2 db call
     }
     dbContext.Complete();
}
于 2012-02-16T23:07:46.930 回答
1

我认为您需要做的是强制您的上下文共享单个数据库连接。然后,您将能够在单个事务中针对两个不同的上下文执行这两个操作。您可以通过将一个 EntityConnection 对象传递给上下文的两个构造函数来实现此目的。当然,这种方法将要求您将此对象传递给更新数据库的方法。

我最近写了一篇关于创建数据库上下文范围的博客,这将使使用多个 EF 上下文和事务更容易。

于 2013-01-05T19:12:48.310 回答