0

コードリファクタリングが原因で問題が発生しました。この場合の最善の解決策は何ですか?

問題は、DbConnectionがローカルメソッド変数からクラス変数にリファクタリングされたことです。アプリケーションはマルチスレッドです。問題は、DbConnectionオブジェクトがメンバー変数である場合に共有されることにあるようです。最善の解決策は何ですか?ローカルメソッド変数として残しますか?

public IDataReader Execute(CommandBehavior behavior, string[] parameterNames, object[] arguments)
{

        DbConnection conn = null;
        try
        {

            conn = Connection.CreateConnection();

            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = StoredProcedureName;
            cmd.CommandType = CommandType.StoredProcedure;



           //     ..................................................

            // Perform the call.                        
            return DataCachingContext.SetCachedData(call, cmd.ExecuteReader(behavior));

        }
        catch (Exception ex)
        {
            //..........................
        }
        finally
        {
            //
        }

}

明確にするために、ここに問題を引き起こすバージョンがあります。実行時の例外、ResultSetへのインデックス作成の問題を除いて、これは接続が上書きされていることが原因である可能性があります。

DbConnection _conn = null;

public IDataReader Execute(CommandBehavior behavior, string[] parameterNames, object[] arguments)
{

        try
        {

            _conn = Connection.CreateConnection();

            DbCommand cmd = _conn.CreateCommand();
            cmd.CommandText = StoredProcedureName;
            cmd.CommandType = CommandType.StoredProcedure;



           //     ..................................................

            // Perform the call.                        
            return DataCachingContext.SetCachedData(call, cmd.ExecuteReader(behavior));

        }
        catch (Exception ex)
        {
            //..........................
        }
        finally
        {
            //
        }

}

さらに調査したところ、ユニットテストを可能にするためにDbConnection変数がクラス変数になっているようです。ローカル変数の場合、その値をテストする方法はありません。DbConnectionの状態がテストされていました

4

5 に答える 5

4

私はあなたがロックステートメントを探していると思います 。

ロックは、別のスレッドがクリティカルセクションにある間、1つのスレッドがコードのクリティカルセクションに入らないようにします。別のスレッドがロックされたコードを入力しようとすると、オブジェクトが解放されるまで待機、ブロックします。

于 2012-08-13T14:53:13.280 に答える
1

アプリケーションはマルチスレッドです。問題は、DbConnectionオブジェクトがメンバー変数である場合に共有されることにあるようです。最善の解決策は何ですか?ローカルメソッド変数として残しますか?

はい、使用するのに適したパターンDbConnectionは、メソッドで接続を作成して破棄することです(ローカル変数に保存します)。舞台裏では接続がプールされているため、このようにすることで大きなオーバーヘッドは発生しません。また、共有状態とロックを処理する必要がなくなります。

質問で提供されたコードは、私がここで説明したことを正確に実行します。

于 2012-08-13T15:03:11.880 に答える
1

データベース接続は、任意の期間開いたままにしておくには比較的高価なリソースであるため、通常、データベース接続オブジェクトはローカル変数である必要があります。データベース接続をクラス変数として持つことの危険性は、オブジェクトがインスタンス化されたときに接続が開かれ、クラスが破棄されるまで開いたままになることです。これにより、ロックがタイムリーに解放されず、トランザクションが長時間実行され、パフォーマンスに深刻な影響を与える可能性があります。

必要になる直前に接続を開き(たとえば、ストアドプロシージャを呼び出し、SQLステートメントを実行する)、直後に接続を閉じて破棄することをお勧めします。カバーの下では、データベース接続は通常、とにかくキャッシュされます。これにより、接続を繰り返し開いたり閉じたりする際のオーバーヘッドが最小限に抑えられます。コードで接続を開くと、キャッシュからすでに開いている接続を取得する可能性があるためです。

于 2012-08-13T15:01:44.087 に答える
1

MSDNのドキュメントには次のように書かれていDbConnectionます。

インスタンスメンバーは、スレッドセーフであることが保証されていません。

したがって、私の意見では、クラス変数として保持することはほとんど良い考えではありません。実装はスレッドセーフである可能性がありますが、そのように想定するのは危険です。ロックを使用してスレッドの問題を回避できますが、これらのアプローチは通常、拡張性が低い傾向があります。したがって、オブジェクトをローカルに保つ方がよいでしょう。

常に開いたり閉じたりする接続が多すぎる場合のパフォーマンスが心配な場合は、オブジェクトではなく実際の接続をプールするのに非常に適したSQL Server接続プール(ADO.NET)を参照してください。DbConnection

于 2012-08-13T15:06:04.033 に答える
0

両方のコードスニペットで、新しい接続を作成します。そのとき、接続をクラス変数にする意図は何でしたか?投稿したコードから、接続はローカル変数である必要があるようです。

于 2012-08-13T15:46:14.777 に答える