使用实体框架的外部System.Common.DBTransaction



我被困在一个问题,将发生在ADO的每个人。. NET与实体框架上下文混合。我有一个大的过程,处理和保存数据到数据库中使用多种方式,如ADO。. NET数据适配器和针对DB的直接CRUD命令。所有的过程都被2个using()块包装起来,这些块创建和释放一个DBConnection/DBTransaction和一个try/catch块来提交或回滚事务。不幸的是,在这个例程的中间,我不得不回忆使用实体框架实现的保存过程。这给我带来了一个问题:

根据官方文档,实体框架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();
            }
        }

我不太明白你的问题,也不确定你的问题是否与如何处理事务有关,或者你是否对EF5到EF6迁移有疑问。话虽如此,你有一个有趣的混合数据访问代码。

关于事务——我会考虑使用TransactionScope,它是系统的一部分。交易名称空间。

例如:

    try
    {
        using (var scope = new TransactionScope())
        {
            using (var conn = new SqlConnection("your connection string"))
            {
                conn.Open();
                // your EF and ADO.NET code
            }
            scope.Complete();
        }
    }
    catch (TransactionAbortedException ex)
    {
    }
    catch (ApplicationException ex)
    {
    }

相关内容

最新更新