实体框架中的一个事务中包含多个数据库



我为实体框架中的两个不同数据库创建了两个不同的上下文。现在我正在尝试在单个事务中更新这些数据库。我的代码是这样的:

public class LPO_BLL
{
    internal Context1 _context1 = null;
    internal Context2 _Context2 = null;
    public LPO_Detail_BLL(Context1 context1, Context2 context2)
    {
        _context1 = context1;
        _context2 = context2;
    }
    public void Insert(PM_LPO lpo, LPO_Transaction lpo_transaction)
    {
        using (TransactionScope transaction = new TransactionScope())
        {
            _context1.LPO.Add(lpo);
            _context1.SaveChanges();
            _context2.LPO_Transaction.Add(lpo_transaction);
            _context2.SaveChanges();  // I am getting error here...
            transaction.Complete();
        }
    }
}

在UI项目中,我称之为:

LPO lpo = new LPO();
//setting properties of lpo
LPO_Transaction lpo_trans = new LPO_Transaction();
//setting properties of lpo_trans
Context1 _context1 = new Context1();
//Opening _context1 connection and etc
Context2 _context2 = new Context2();
//Opening _context2 connection and etc
LPO_BLL lpo_bll = new LPO_BLL(_context1, _context2);
lpo_bll.Insert(lpo,lpo_trans);

目前,我犯了一个错误:基础提供商在EnlistTransaction上失败

在互联网上搜索了过去3个小时,并尝试了不同的点击和试用方法后,我决定把这个放在SO上。到目前为止,我发现这两个链接更接近:

http://social.msdn.microsoft.com/Forums/en-US/3ccac6f7-6513-4c87-828a-00e0b88285bc/the-underlying-provider-failed-on-enlisttransaction?forum=adodotnetentityframework

TransactionScope-基础提供程序在EnlistTransaction上失败。MSDTC中止

并非所有DB提供程序都支持分布式事务。

使用事务作用域将尝试在MSDTC管理的分布式事务中登记DB事务。如果您的提供商不支持此功能,它将失败。

SQL Server和Oracle提供程序支持分布式事务。但许多其他EF提供商没有。

如果你的数据库提供商不支持这一点,你将不得不使用另一个,或者放弃使用事务。

如果您使用的是SQLServer2005,它应该可以工作,但是:

  • MSDTC服务必须正在运行(请在"控制面板"的"服务"中查找)
  • 连接字符串必须足够MSDTC工作

看看这个SO问答;A: 关于事务和msdtc的混淆。

注意:服务的名称为MSDTC。因此,您可以运行net start msdtcnet stop msdtc。如果你在控制面板中寻找它,你会发现一个描述性的名称,比如"分布式事务协调器",或者一个本地化的名称,就像"Coordinador de transacciones distribidas"。奇怪的是,没有办法在本地服务的控制面板列表中显示名称列。

您必须在DbContext中使用ObjectContext才能使用参数为的SaveChanges

public class EntityDBContext: DbContext, IObjectContextAdapter
{
    ObjectContext IObjectContextAdapter.ObjectContext {
        get { 
           return (this as IObjectContextAdapter).ObjectContext;
        }
    }
}

然后在插入方法中,使用:

public void Insert(PM_LPO lpo, LPO_Transaction lpo_transaction)
{
    using (TransactionScope transaction = new TransactionScope())
    {
         context1.ObjectContext.SaveChanges(false);
         context2.ObjectContext.SaveChanges(false);
         _context1.LPO.Add(lpo);
         _context2.LPO_Transaction.Add(lpo_transaction);       
         transaction.Complete();
         context1.ObjectContext.AcceptAllChanges();
         context2.ObjectContext.AcceptAllChanges();
    }
}

对于多个数据库,应使用Savechange(false)和AcceptAllChanges()集。

 public void Insert(PM_LPO lpo, LPO_Transaction lpo_transaction)
{
    using (TransactionScope transaction = new TransactionScope())
    {
         context1.SaveChanges(false);
         context2.SaveChanges(false);
        _context1.LPO.Add(lpo);
        _context2.LPO_Transaction.Add(lpo_transaction);       
        transaction.Complete();
       context1.AcceptAllChanges();
       context2.AcceptAllChanges();
    }
}

最新更新