16

Entity Framework(私の場合は最初にコード)を使用して、SaveChangesを呼び出してDB内の1つのオブジェクトを更新してから、もう一度SaveChangesを呼び出して別のオブジェクトを更新する必要がある操作があります。(EFが最初に更新するオブジェクトを特定できない問題を解決するには、最初のSaveChangesが必要です)。

私はやってみました:

using (var transaction = new TransactionScope())
{
    // Do something

    db.SaveChanges();

    // Do something else

    db.SaveChanges();

    tramsaction.Complete();
}

SaveChangesこれを実行すると、2回目の呼び出しで、「基になるプロバイダーがオープンに失敗しました」という例外が発生します。内部例外は、MSDTCが私のマシンで有効になっていないことを示しています。

さて、MSDTCを有効にする方法を説明する投稿を他の場所で見ましたが、ネットワークアクセスなども有効にする必要があるようです。他のサーバーはもちろん、他のデータベースが関与していないため、これは完全にやり過ぎのようです。アプリケーション全体の安全性を低下させる(または遅くする)ようなことはしたくありません。

確かに、これを行うためのより軽量な方法が必要です(理想的にはMSDTCなしで)?!

4

3 に答える 3

13

ちょっと遅い答えだとは思いますが、共有するのは便利だと思いました。

EF6では、を使用してこれを達成するのが簡単になりましたdbContext.Database.BeginTransaction()

このような :

using (var context = new BloggingContext())
{
    using (var dbContextTransaction = context.Database.BeginTransaction())
    {
        try
        {
            // do your changes
            context.SaveChanges();

            // do another changes
            context.SaveChanges();

            dbContextTransaction.Commit();
        }
        catch (Exception)
        {
            dbContextTransaction.Rollback();
        }
    }
}

詳細については、これを見てください

再びEF6以降にあります

于 2014-04-26T09:24:02.170 に答える
8

これは、トランザクションで使用された2つの異なる接続が原因である可能性があります。操作の接続を手動で制御してみてください。

var objectContext = ((IObjectContextAdapter)db).ObjectContext;

try {
    //Open Connection
    objectContext.Connection.Open();

    using (var transaction = new TransactionScope()) {
        // Do something

        db.SaveChanges();

        // Do something else

        db.SaveChanges();

        transaction.Complete();
    }
} finally {
    //Close connection after commit
    objectContext.Connection.Close();
} 
于 2012-10-10T09:26:01.660 に答える
7

そのままSaveChanges()を呼び出すことにより、データがデータベースに永続化され、EFは今行った変更を忘れます。

秘訣は、SaveChanges(false)を使用して、変更がDBに保持されるようにすることですが、EFは変更を忘れないため、ログ記録/再試行が可能になります。

        var scope = new TransactionScope(
            TransactionScopeOption.RequiresNew,
            new TransactionOptions() { IsolationLevel = IsolationLevel.Serializable }
        );

        using (scope)
        {
            Entities context1 = new Entities();
            // Do Stuff
            context1.SaveChanges(false);

            Entities context2 = new Entities();
            // Do Stuff
            context2.SaveChanges(false);

            scope.Complete();
            context1.AcceptAllChanges();
            context2.AcceptAllChanges();
        }

PSトランザクションスコープ内で複数の接続を開くとすぐに、DTCにエスカレーションします。

于 2013-02-26T10:52:08.843 に答える