コンテキスト間のトランザクション

asp.net-core entity-framework entity-framework-core

質問

私はEntity Framework Core(7)を使ってコンソールアプリケーションを開発しています。

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

エンティティフレームワーク6には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)

受け入れられた回答

TransactionScopeはEntity Frameworkの一部ではありません。 System.Transactions名前空間の一部です。さらに、TransactionScopeはEntity Framework 6.xとのトランザクション処理に推奨される方法ではありません。

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
                }
            }
        }


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ