4

最初にEF5コードと.NET4.5を使用するMVCプロジェクト。

単一のトランザクションでdbContextとSimpleMembershipProviderをラップする方法を探していました。TransactionScopeを使用しようとしましたが、メンバーシッププロバイダーが別の接続を開くため、例外が発生します(サーバー'servername'のMSDTCは使用できません)。

したがって、代わりにObjectContext.Connection.BeginTransactionを使用できます。メンバーシッププロバイダーはトランザクションの一部にはなりませんが、失敗した場合にトランザクションがコミットされない場所にメンバーシッププロバイダーを配置することを目的としています。

Book bk1 = default(Book);
Book bk2 = default(Book);

object obc = (IObjectContextAdapter)dbContext;

obc.ObjectContext.Connection.Open();
using (tx == obc.ObjectContext.Connection.BeginTransaction) {

    bk1 = new Book {
        Name = "Book 1 Name",
        Location = "USA"
    };
    dbContext.Books.Add(bk1);
    dbContext.SaveChanges();
    bk2 = new Book {
        Name = "Book 2 Name. Book one Id is: " + bk1.Id,
        Location = "USA"
    };
    dbContext.Books.Add(bk2);
    dbContext.SaveChanges();

    // this is not part of the transaction, 
    // however if it trhows an exception the transaction is aborted.
    // I'm assuming that if we got here, the commit won't fail...    
    // But is it really true?
    WebSecurity.CreateUserAndAccount("username", "123456");

    tx.Commit();
}

とにかく、上記のコードに基づいて:

  • WebSecurity.CreateUserAndAccountが失敗すると、すべてが失敗します。これは予想どおりです。
  • SaveChangesメソッドのいずれかが失敗した場合、CreateUserAndAccountが実行されるポイントに到達しないため、もう一度すべてが失敗します。

このすべてが私に質問をもたらします:それは安全ですか?私が意味するのは:

DbContext.SaveChangesを正常に実行した後、「Commit」メソッドが(何らかの理由で失敗した)例外をスローする可能性はありますか?それが発生した場合、プロバイダーはトランザクションの一部ではないため、孤立したユーザーになってしまいます。

これについてのコメントやアドバイスに感謝します。

クイックノート:独自の接続プロパティを使用する代わりにdbContextをIObjectContextadapterにキャストする必要がある理由を説明するこの素晴らしい記事がありますが、もう見つかりません。

4

1 に答える 1

2

はい、Commit確かに投げることができます。些細な例の 1 つは、接続が切断された場合です。もちろん、他のケースもあります。

いくつかの選択肢があります:

  • 接続が共有されている場合、同じ DB 上のトランザクションは分散にエスカレートされません。したがって、EF と接続の両方に 1 つの接続を使用できますWebSecurity
  • サーバーで分散トランザクション コントローラーを起動し、エスカレーションに対応します。世界で最悪のことではありません。
  • トランザクションを使用する代わりに、部分的に成功した操作を後で完了または元に戻すことができるように、操作の順序を変更します。たとえば、「孤立した」ユーザーを検出してクリーンアップします。
于 2012-09-07T17:20:19.713 に答える