我正在使用一组现有代码来管理单个事务中的多个数据库更新。这是一个简化的例子:
Database db = DatabaseFactory.CreateDatabase();
using (DbConnection dbConnection = db.CreateConnection())
{
dbConnection.Open();
DbTransaction dbTransaction = dbConnection.BeginTransaction();
try
{
//do work
dbTransaction.Commit();
}
catch (Exception ex)
{
dbTransaction.Rollback();
}
}
我也在同一个项目中使用EntityFramework进行新开发。下面是我的存储库类的使用的简化示例:
List<ThingViewModel> things = new List<ThingViewModel>();
// populate list of things
IObjectRepository thingRepository = new ThingRepository();
thingRepository.AddThings(things);
thingRepository.Save();
我希望在“AddThings”中完成的工作在第一个代码块中作为事务的一部分发生。
是否有一些干净的方法将我的存储库模式混合到现有代码中,反之亦然?我还没有将现有代码重写为完全在EntityFramework中的可行性,所以我正在寻找一些临时方法。
我已经尝试将事务从旧代码传递到存储库,从而实现了EntityFramework,但这似乎不起作用。我还尝试将ObjectContext传回旧代码,以便在事务中登记它。这两种方法都不奏效。
我无法相信我是第一个在将现有代码迁移到EntityFramework时遇到这个障碍的人......必须有一些我不考虑的事情。
我将列出我在下面尝试的内容:
using (TransactionScope transactionScope = new TransactionScope())
{
Database db = DatabaseFactory.CreateDatabase();
using (DbConnection dbConnection = db.CreateConnection())
{
dbConnection.Open();
DbTransaction dbTransaction = dbConnection.BeginTransaction();
try
{
//do work
dbTransaction.Commit();
}
catch (Exception ex)
{
dbTransaction.Rollback();
}
}
Thing thing = new Thing(){
Prop1 = Val1,
Prop2 = Val2
};
ThingObjectContext context = new ThingObjectContext();
context.Things.AddObject(thing);
context.SaveChanges();
transactionScope.Complete();
}
这最后一个例子“有效”,它不能作为一个交易。当EF插入失败时,TransactionScope不会回滚EL命令。如果我没有将这些显式调用放到.Commit()和.SaveChanges(),则没有任何反应。如果可能的话,我真的希望能够共享相同的连接。我目前正在使用的另外两个变体是尝试在EF和EL之间使用相同的连接,以及在一侧或另一侧使用EnlistTransaction。绝对试图阻止它成为MSDTC - 不希望与此相关的额外开销。
答案 0 :(得分:2)
使用TransactionScope而不是显式事务管理。您将简化整体代码,您所做的一切都应该自动检测并使用相同的事务。
答案 1 :(得分:1)
有什么方法可以在您的EL代码中调用Database.GetOpenConnection()
而不是CreateConnection()
,并传递您在things.Connection
块内创建的TransactionScope
?我没有对此进行测试,但这是我首先尝试的。