2016-12-07 10 views
2

私は、Entity Framework Core(7)を使用してコンソールアプリケーションを開発しています。コンテキスト間のトランザクション

アプリケーションは3つの異なる領域に分かれていますが、データベースは共有されています。 私は3種類のDbContextを作成しましたが、それらの間でトランザクションを実行する必要があります。 私はすべての変更または何も(ロールバック)を保存する原子操作が必要です。

エンティティframeowrk6には、TransactionScopeというクラスがありましたが、EFコアには別のものがあります。次のコードを使用して

public static void Main(string[] args) 
    { 
     var options = new DbContextOptionsBuilder<DbContext>() 
     .UseSqlServer(new SqlConnection("Server=x.x.x.x,1433;Database=test;user id=test;password=test;")) 
     .Options; 

     var cat = new Cat { Name = "C", Surname = "C", Age = 55 }; 
     var dog = new Dog { Date = DateTime.Now, Code = 120, FriendId = cat.Id }; 


     using (var context1 = new DogsContext(options)) 
     { 
      using (var transaction = context1.Database.BeginTransaction()) 
      { 
       try 
       { 
        context1.Dogs.Add(dog); 
        context1.SaveChanges(); 

        using (var context2 = new CatsContext(options)) 
        { 
         context2.Database.UseTransaction(transaction.GetDbTransaction()); 
         context2.Cats.Add(cat); 
        } 

        transaction.Commit(); 
       } 
       catch (Exception e) 
       { 
        Console.WriteLine(e); 
        transaction.Rollback(); 
       } 
      } 
     } 
    } 

を私は次のエラーを取得する:

System.InvalidOperationException: ExecuteScalar requires the command to have a transaction when the connection assigned to the co 
mmand is in a pending local transaction. The Transaction property of the command has not been initialized. 
    at System.Data.SqlClient.SqlCommand.ValidateCommand(Boolean async, String method) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStrea 
m, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteScalar() 
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMe 
thod, IReadOnlyDictionary`2 parameterValues, Boolean openConnection, Boolean closeConnection) 
    at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists() 
    at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration) 
+0

'TransactionScope'はまだ実装されていませんが、そのはnetstandard2.0''に来て私の知る限り、2017年のある時点しかし、あなたは仕事パターンのユニットを試すことができます – Tseng

答えて

2

TransactionScopeは、Entity Frameworkの一部ではありません。 System.Transactions名前空間の一部です。さらに、TransactionScopeは、Entity Framework 6.xとのトランザクションを処理するためのrecommended approachではありません。

Entity Framework Coreを使用すると、リレーショナルデータベースのみの複数のコンテキストでトランザクションを共有できます。ここ

詳細情報:https://docs.microsoft.com/en-us/ef/core/saving/transactions

例(テストしていません):

 using (var context1 = new YourContext()) 
     { 
      using (var transaction = context1.Database.BeginTransaction()) 
      { 
       try 
       { 
        // your transactional code 
        context1.SaveChanges(); 

        using (var context2 = new YourContext()) 
        { 
         context2.Database.UseTransaction(transaction.GetDbTransaction()); 
         // your transactional code 
        } 

        // Commit transaction if all commands succeed, transaction will auto-rollback when disposed if either commands fails 
        transaction.Commit(); 
       } 
       catch (Exception) 
       { 
        // handle exception 
       } 
      } 
     } 
+0

ウィリアムありがとう。 YourContextを2回使用している例です。あなたがUsersContextとOrderContextのようなものを持っていれば動作しません – BlackEye

+0

私の例は同じコンテキストタイプのものですが、複数のコンテキストインスタンス間でトランザクションを共有することもできます。 EFのコアドキュメント(参照先のリンクを参照)によると、 - "複数のコンテキストインスタンス間でトランザクションを共有することもできます"。 –

+0

そのコードを使用すると、トランザクション例外が発生します。オープン・ポストをより詳細に更新しました。ありがとうございました – BlackEye

関連する問題