0

asp.net メンバーシップを MVC4 の新しい simplemembership プロバイダーにアップグレード中です。これは Azure/Sql Azure アプリで、localhost では問題なく動作しますが、展開すると失敗します。次のように、トランザクションにコードがあります。

            TransactionOptions toptions = new TransactionOptions();
            toptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
            using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required, toptions))
            {
                try
                {
                   ... do a bunch of database stuff in a single dbContext ...

                   var roleprov = (SimpleRoleProvider)Roles.Provider;
                   string[] roles = roleprov.GetRolesForUser(Username);
                   // above line fails with The transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D024)
                 }
             }

この手法を使用して Roles クラスを作成しています。スタック トレースは、その呼び出しを完了するために実際にサブトランザクションを起動しようとしていることを示しているようです。simplemembership テーブルは別のデータベースにあります。別のトランザクションのコンテキスト内でロール プロバイダーからロール情報を取得するにはどうすればよいですか?

4

1 に答える 1

0

問題はGetRolesForUser、2 番目のデータベースへの新しい接続が開かれ、TransactionScope. 次に、これ ( MSDN - System.Transactions Integration with SQL Server ) が DTC に昇格します。いくつかのオプションを試すことができます:

トランザクション開始前にロールを取得

string[] roles の外で取得できますTransactionScope。それらをスコープ内に入れる必要がある理由はありますか?あなたが言うことを考えると:

別のトランザクションのコンテキスト内でロール プロバイダーからロール情報を取得するにはどうすればよいですか

の前にロール情報を取得できたようで、TransactionScope問題はありません。

シンプル メンバーシップ接続文字列でトランザクションをオフにする

接続文字列に「enlist=false」(「参考文献」を参照SqlConnection.ConnectionString) を入力することで、接続文字列がトランザクションに参加しないように指定できます。そのため、シンプル メンバーシップに使用するデータベースでトランザクションがまったく必要ない場合は、これが 1 つのオプションになる可能性があります。

トランザクションの前にシンプル メンバーシップ接続を開いてみてください

データベースオブジェクトを作成し、SimpleRoleProvider最初に使用するときにそれを開きます。しかし、... まで閉じませんそれをスクラッチすると、への呼び出しごとに接続が開かれるGetRolesForUserので、運が悪いです。GetRolesForUserが開かれる前に一度呼び出してからTransactionScope、すでに開いている接続を使用してスコープ内で再度呼び出すことができると考えていましたが、できません。

で遊ぶIObjectContextAdapter

免責事項:あなたのセットアップでテストできないため、これが機能するとは約束できません。

最初にトランザクション スコープ外の非トランザクション接続文字列を開くことで、2 つの接続文字列で昇格を防止するトリックを実行できます。その後、トランザクションは昇格されません。これは、同じ接続を同じトランザクション スコープ内で発生させた場合にも使用できます (それ以外の場合は昇格が発生しますClose) 。Open

コンテキストでこれを試して、それが GetRolesForUser によるトランザクションの促進を停止したかどうかを確認できますが、まだGetRolesForUser接続されていない場合、接続が開かれる原因として機能するとは思えません。あなたのシナリオではテストできないので、役立つ場合に備えて含めます。

using (var db = new ExampleContext())
{
    var adapter = db as System.Data.Entity.Infrastructure.IObjectContextAdapter;
    using (var conn = adapter.ObjectContext.Connection)
    {
        conn.Open();
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            // perform operations
            db.SaveChanges();
            // perform more operations
            db.SaveChanges();
            // perform even more operations
            db.SaveChanges();

            //  If you don't complete, the transaction won't commit and you will lose the changes
            scope.Complete();
        }
    }
}
于 2013-05-22T18:46:50.240 に答える