在一个事务范围内使用EF将数据写入两个数据库

时间:2016-08-12 20:36:30

标签: c# entity-framework transactions msdtc

我们正在使用Entity Framework 6并正在处理以下要求:

  • 我们正在将数据写入两个不同的独立数据库,我们称之为Main和External,它们都存在于同一个SQL Server实例上,用于连接它们的连接字符串是相同的,除了初始目录值

  • 在应用程序中,每个DB都有自己的EF DBContext。

  • 主数据库有一个AuditLog表,其中记录了数据更改。

  • 外部数据库上发生的数据更改需要记录在主数据库中的AuditLog表中。

由于某些限制并不重要,讨论我们实现的方式是让ExternalContext有一个MainContext的引用,以便每当调用ExternalContext.SubmitChanges时调用MainContext.SaveAuditLogs,就像这样(只显示相关代码) :

public class ExternalContext : IDataContext
{
    private readonly IAuditLogContext auditLogContext;

    public ExternalContext (IAuditLogContext auditLogContext){
        this.auditLogContext = auditLogContext;
    }

    public override void SaveChanges()
    {
        base.SaveChanges();
        this.auditLogContext.SaveAuditLogs(auditLogs);
    }
}

public class MainContext : IAuditLogContext
{
    public void SaveAuditLogs(List<AuditLog> auditLogs)
    {
        this.Set<AuditLog>().AddRange(auditLogs);

        this.SaveChanges();
    }
}

如何使用它的一个例子:

public class SomeBusinessClass
{
    private readonly IDataContext dataContext;

    public SomeBusinessClass(IDataContext dataContext)
    {
        this.dataContext = dataContext;
    }

    public void SomeOperation(Entity someEntity)
    {
        .....

        using(var scope = new TransactionScope())
        {
            this.dataContext.Insert(someEntity);
            this.dataContext.SaveChanges();
        }
        scope.Complete();
    }
}

为此,分布式事务处理协调器服务需要运行。在开发环境中进行测试时,它可以正常工作,但在QA环境中,它会因错误消息而失败,就像分布式事务处理协调器即使没有运行一样。

显然这是因为在我们的开发环境中,数据库服务器和Web服务器在QA中是相同的计算机天气,它们是两个独立的盒子,当有多个服务器并且这两个操作在TransactionScope中运行时,DTC不喜欢它,如果我们删除TransactionScope,那么它在两种环境下都能正常工作,但是如果AuditLog失败则不会回滚整个事务。

我们怎样才能做到这一点?

谢谢。

0 个答案:

没有答案