【发布时间】:2016-10-31 09:45:39
【问题描述】:
我遇到了一个问题,该问题将在 ADO.NET 中与实体框架上下文混合时发生在每个人身上。 我有一个大程序,通过使用多种方式(如 ADO.NET 数据适配器和针对 DB 的直接 CRUD 命令)来处理并将数据保存到数据库中。所有过程都由 2 个 using() 块包装,这些块创建和释放一个 DBConnection/DBTransaction 和一个 try/catch 块以提交或回滚事务。不幸的是,在这个例程的中间,我不得不回忆一个使用实体框架实现的保存过程。这给我带来了一个问题:
根据官方文档,Entity Framework 5 允许我通过与事务相关的事务的连接(它应该在调试模式下工作,当我调用 SaveChanges() 时,由于死锁,我没有收到任何 TimeOutException,相反如果我通过了一个新的连接,它确实如此),但不幸的是,在 SaveChanges() 启动后,连接关闭并提交了关联的事务!即使我设置了“contextOwnsConnection”标志!
据我所知,如果我将 EF5 迁移到 EF6,事情应该可以工作(对吗?),但不幸的是我不能,因为我正在处理的项目非常大并且涉及很多依赖项这将花费大量时间。
如何使它与 EF5 一起使用?是否有任何技巧或模式来达到预期的结果?我对 EF6 的行为是否正确?是否值得迁移 EF6?
这是一个简单的示例,说明我的代码是什么样的。 出于隐私原因,我无法发布原始代码,只是想象一下这种情况更加复杂:
using(DbConnection conn = DBProvider.CreateConnection()){
//Open the created connection
conn.Open();
//Create a new transaction
using(DbTransaction tr = DBProvider.CreateTransaction()){
//Begin a new transaction
tr.Begin();
bool saveOk;
try{
//Updates customers by using dataadapter
dataAdapterCustomers.InsertCommand.Transaction = tr;
dataAdapterCustomers.UpdateCommand.Transaction = tr;
dataAdapterCustomers.DeleteCommand.Transaction = tr;
dataAdapterCustomers.Update();
//Updates stock items by using dataadapter
stockAdapterCustomers.InsertCommand.Transaction = tr;
stockAdapterCustomers.UpdateCommand.Transaction = tr;
stockAdapterCustomers.DeleteCommand.Transaction = tr;
stockAdapterCustomers.Update();
//...Many other DB accessing here...
//Updates stock quantity by using simple DBCommand
quantityUpdateCmd.Transaction = tr;
quantityUpdateCmd.ExecuteNonQuery();
//Updates stock statistics by using a simple DBCommand
updateStockStatsCmd.Transaction = tr;
updateStockStatsCmd.ExecuteNonQuery();
//...Many other DB accessing here...
//HERE:
//Creates a new activity and save it using EF.
//I use a UnitOfWork and i pass to it my connection and 'false' as contextOwnsConnection parameter
//(it 'll be used by the DBContext contained in my Unit of work)
using(ActivityUoW uow = new ActivityUoW(conn, false)){
Activity act = new Activity();
act.Name = "Saving activity";
act.Description = "Done by user";
act.Date = DateTime.Now;
uow.Activities.Add(act);
uow.SaveChanges();
}
//Based on activity result, launch a store procedure that makes other complex things.
UNFORTUNATELY THE CONNECTION HAS BEEN CLOSED AND TRANSACTION COMMITTED, SO THE FOLLOWING INSTRUCTION WILL FAIL.
launchActivityUpdateSpCmd.Transaction = tr;
launchActivityUpdateSpCmd.ExecuteNonQuery();
//...Many other DB accessing here...
//Data saved correctly
saveOk = true;
}
catch(Exception ex){
//There was an error during save
saveOk = false;
}
//Commit or rollback transaction according to save procedure result
if(saveOk)
tr.Commit();
else
tr.Rollback();
}
}
【问题讨论】:
标签: c# entity-framework transactions ado.net dbconnection