0

ASP.NET でストアド プロシージャを呼び出す汎用メソッドがあります。

public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
        {
            SqlDataReader iReader;
            SqlCommand sql = new SqlCommand();

            sql.CommandText = sprocName;
            sql.CommandType = CommandType.StoredProcedure;
            sql.Connection = ConnStr;
            if (SqlP != null)
            {
                foreach (SqlParameter p in SqlP)
                {
                    sql.Parameters.Add(p);
                }

            }
            sql.Connection.Open();
            iReader = sql.ExecuteReader(CommandBehavior.CloseConnection);
            sql.Dispose();

            return iReader;
        }

CommandBehavior.CloseConnection を呼び出していますが、接続が閉じていません。初めてページをリクエストしたときに、データをうまく取得できます。リロードすると、次のエラーが表示されます。

接続は閉じられませんでした。接続の現在の状態はオープンです。説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。

例外の詳細: System.InvalidOperationException: 接続が閉じられませんでした。接続の現在の状態はオープンです。

ソース エラー:

35 行目: 36 行目: } 37 行目: sql.Connection.Open(); 行 38: iReader = sql.ExecuteReader(CommandBehavior.CloseConnection); 行 39: sql.Dispose();

最後に sql.Connection.Close(); を入れたら 前に sql.Dispose(); iReader は既に閉じられているため読み取れないというエラーが表示されます。

明らかに、接続を誤って閉じています。誰かが私を正しい方向に向けることができますか?

4

4 に答える 4

4

DataReader を返すときは、基になる接続を開いたままにしておく必要があります。リソースを適切にクリーンアップするのは、消費者の責任です。

public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
    SqlCommand sql = new SqlCommand();

    sql.CommandText = sprocName;
    sql.CommandType = CommandType.StoredProcedure;
    sql.Connection = ConnStr;
    if (SqlP != null)
    {
        foreach (SqlParameter p in SqlP)
        {
            sql.Parameters.Add(p);
        }

    }
    sql.Connection.Open();
    return sql.ExecuteReader(CommandBehavior.CloseConnection);          
}

public void ConsumingMethod()
{
    using(SqlDataReader reader = ExecuteStoredProc("MyProc", params))
    {
        while(reader.Read())
        {
            //work with your reader
        }
    }
}
于 2009-06-03T20:13:06.293 に答える
0

これは、IDataReader を処理するための私の好みの方法です。呼び出し元に SqlConnection インスタンスを作成させ、メソッドに渡します。

SqlConnection インスタンスの作成にはコストがかかります。そして、異なる状況でコードが同じ ExecuteStoredProc メソッドを複数回呼び出すことになります。

したがって、パラメーターの一部として SqlConnection インスタンスを追加して、ExecuteStoredProc メソッドをリファクタリングします。

using (SqlConnection conn = new SqlConnection())
{
    conn.ConnectionString = // Connection String;
    conn.Open();

    using (IDataReader reader = foo.ExecuteStoredProc(conn, sprocName, SqlP))
    {
        // Process IDataReader
    }
}
于 2009-06-03T21:00:11.643 に答える
0

アイデアは、 Connection.Close(); を実行することです。つまり、SqlReader.Dispose() コマンドの前に close() ステートメントを配置する代わりに、以下に配置する必要があります。

于 2009-06-03T20:28:03.687 に答える