2016-06-28 4 views
0

Entity Frameworkコンテキストと混在するADO.NETの全員に起こる問題に悩まされています。 私は、ADO.NETデータ・アダプターのような複数の方法を使用し、DBに対して直接CRUDコマンドを使用することによって、データベースにデータを処理して保存する大きな手順を持っています。すべてのプロシージャは、トランザクションをコミットまたはロールバックするためのDBConnection/DBTransactionおよびtry/catchブロックを作成および解放するブロックを使用して2つのラップされます。残念ながら、このルーチンの途中で、Entity Frameworkを使用して実装された保存プロシージャを思い出す必要があります。Entity Framework 5でExternal System.Common.DBTransactionを使用します。

公式のドキュメントによると、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(); 
      } 
     } 

答えて

0

ともし確認されませんでしたあなたの問題はトランザクションの処理方法やEF5からEF6への移行に関する質問があった場合に関係していました。つまり、興味深いデータアクセスコードが混在しています。

トランザクションについて - System.Transactions名前空間の一部である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) 
    { 

    } 
+0

TransactionScopeのはいいですね、それは私のスコープ内のトランザクションを設定するために働く必要があります。しかし、EF SaveContext()の後に接続を閉じるとどうなりますか? EFはトランザクションスコープでDbConnectionを開いたままにしますか?私がそうでなければ、EF5からEF6への移行を離れて何をすることができますか? – GiveEmTheBoot

+0

接続オブジェクトが使用ブロックにあります。接続は切断されます。ブロック呼び出しを使用Dispose()。 –

+0

はい、私はそれを知っていますが、launchActivityUpdateSpCmdコマンドはどうでしょうか?以前のコード行のEF5 SaveChanges()動作のために、その時点で接続がすでに閉じられているため、機能しません。 – GiveEmTheBoot

関連する問題