web-dev-qa-db-ja.com

SqlDataReaderを手動で閉じて廃棄する必要がありますか?

ここではレガシーコードを使用していますが、SqlDataReaderの多くのインスタンスが閉じられたり破棄されたりすることはありません。接続は閉じていますが、リーダーを手動で管理する必要があるかどうかはわかりません。

これによりパフォーマンスが低下する可能性がありますか?

83
Jon Ownbey

このようなリーダーを使用しないようにしてください。

SqlConnection connection = new SqlConnection("connection string");
SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection);
SqlDataReader reader = cmd.ExecuteReader();
connection.Open();
if (reader != null)
{
      while (reader.Read())
      {
              //do something
      }
}
reader.Close(); // <- too easy to forget
reader.Dispose(); // <- too easy to forget
connection.Close(); // <- too easy to forget

代わりに、usingステートメントでそれらをラップします。

using(SqlConnection connection = new SqlConnection("connection string"))
{

    connection.Open();

    using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader != null)
            {
                while (reader.Read())
                {
                    //do something
                }
            }
        } // reader closed and disposed up here

    } // command disposed here

} //connection closed and disposed here

Usingステートメントは、オブジェクトの正しい廃棄とリソースの解放を保証します。

忘れた場合は、ガベージコレクターに掃除を任せることになります。これには時間がかかる場合があります。

116
Codebrain

SqlCommand.ExecuteReader()を使用してインスタンス化されたSqlDataReaderを破棄すると、基礎となる接続がnotクローズ/破棄されることに注意してください。

2つの一般的なパターンがあります。最初の方法では、リーダーは接続の範囲内で開閉されます。

using(SqlConnection connection = ...)
{
    connection.Open();
    ...
    using(SqlCommand command = ...)
    {
        using(SqlDataReader reader = command.ExecuteReader())
        {
            ... do your stuff ...
        } // reader is closed/disposed here
    } // command is closed/disposed here
} // connection is closed/disposed here

データアクセスメソッドで接続を開き、リーダーを返すと便利な場合があります。この場合、返されたリーダーはCommandBehavior.CloseConnectionを使用して開かれることが重要です。そのため、リーダーを閉じたり破棄したりすると、基になる接続が閉じられます。パターンは次のようになります。

public SqlDataReader ExecuteReader(string commandText)
{
    SqlConnection connection = new SqlConnection(...);
    try
    {
        connection.Open();
        using(SqlCommand command = new SqlCommand(commandText, connection))
        {
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
    catch
    {
        // Close connection before rethrowing
        connection.Close();
        throw;
    }
}

そして、呼び出しコードは単にリーダーを破棄する必要があります:

using(SqlDataReader reader = ExecuteReader(...))
{
    ... do your stuff ...
} // reader and connection are closed here.
49
Joe

安全のため、すべてのSqlDataReaderオブジェクトを sing statement でラップします。

10
Kon

SQLDataReaderを「using」ステートメントでラップするだけです。それはあなたの問題のほとんどの世話をする必要があります。

5
J.W.