具有多个 DbContext 的事务,每个事务在 Entity Framework 上都有自己的连接

Transaction with multiple DbContext and each one with its own connection on Entity Framework

我知道它看起来像是重复的,因为关于多个上下文中的事务有很多问题,但是 none 其中提到了这种情况。

设置

  1. SQL 开发机器上的 Server 2016(最新预览版)或 SQL 生产机器上的 Azure v12
  2. Entity Framework6.1.3
  3. .Net 4.5 在常规应用程序上
  4. 应用程序可以 运行 在 Azure 云服务或 VM 上,这并不重要

我们在代码中有什么

  1. 单个 TransactionScope
  2. 在 TransactionScope 外部 创建了两个 DbContext(它是由我们的依赖注入机制创建的,与 ASP.Net MVC 相关联,所以为了简单起见,我将其排除在范围之外样本)
  3. 每个上下文创建并维护自己的连接,该连接指向不同服务器上的不同数据库(如果 运行 在开发机器上连接,它也可以指向同一服务器,但仍然是不同的数据库)。
  4. 我们使用常规 SQL 身份验证 - 用户 ID 和密码(以防万一有人指出一些 post 谈论集成安全和 MSDTC 的问题,我们不在本地使用它,因为Azure SQL 不支持)

我们的代码示例

当我们做类似的事情时:

var contextA = new ContextA();
var contextB = new ContextB();
using(var scope = new TransactionScope())
{
     var objA = new EntityA();
     objA.Name = "object a";
     contextA.EntitiesA.Add(objA);
     contextA.SaveChanges();

     var objB = new EntityB();
     objB.Name = "object B";
     contextB.EntitiesB.Add(objB);
     contextB.SaveChanges();
     scope.Complete();
}

我们收到什么

在调用 contextA.SaveChanges() 时抛出 System.Data.Entity.Core.EntityException,并显示以下消息:

Root 异常: 基础提供程序在 EnlistTransaction 上失败。

内部异常连接当前已登记事务。完成当前事务并重试。

所以,有人知道这个样本到底出了什么问题吗?

我们试图让一个事务使用多个上下文,每个上下文都有自己的数据库连接。显然,由于每个上下文的数据都在不同的数据库服务器上(在生产中),我们不能使用接收 DbConnection 并将其与两个上下文共享的 DbContext ctor,因此共享 DbConnection 不是一个选项。

非常感谢,非常感谢任何帮助。

据我所知,SQL Azure 不支持分布式事务。 Source

Azure SQL 数据库现在支持使用 TransactionScope 的分布式事务。参见 TransactionScope() in Sql Azure