我在Entity Framework中为两个不同的数据库创建了两个不同的上下文。现在我试图在单个事务中更新这些数据库。我的代码是这样的:
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上。到目前为止,我发现这两个链接更接近:
TransactionScope - The underlying provider failed on EnlistTransaction. MSDTC being aborted
答案 0 :(得分:3)
并非所有数据库提供程序都支持分布式事务。
使用事务范围将尝试在由MSDTC管理的分布式事务中登记数据库事务。如果您的提供商不支持此功能,则会失败。
SQL Server和Oracle提供程序支持分布式事务。但许多其他EF提供商却没有。
如果您的数据库提供商不支持此功能,您将不得不使用其他服务提供商或放弃使用交易。
如果您使用的是SQL Server 2005,它应该可以工作,但是:
请看this SO Q&A: confusion about transactions and msdtc。
注意:服务名称为MSDTC
。因此,您可以运行net start msdtc
或net stop msdtc
。如果您在控制面板中查找它,您将找到一个描述性名称,如“分布式事务处理协调器”或本地化名称,如“Coordinador de transacciones distribuidas”。奇怪的是,没有办法在本地服务的控制面板列表中显示名称列。
答案 1 :(得分:2)
您必须在DbContext中使用ObjectContext才能将SaveChanges与参数一起使用:
public class EntityDBContext: DbContext, IObjectContextAdapter
{
ObjectContext IObjectContextAdapter.ObjectContext {
get {
return (this as IObjectContextAdapter).ObjectContext;
}
}
}
然后在Insert方法中,使用:
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();
}
}
答案 2 :(得分:1)
对于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();
}
}