2009-04-13 24 views
63

私はここでレガシーコードを扱っています。SqlDataReaderの多くのインスタンスが閉じられたり廃棄されたりすることはありません。接続は閉じていますが、読者を手動で管理する必要があるかどうかはわかりません。SqlDataReaderを手動で閉じて処分する必要がありますか?

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

答えて

94

は次のように読者を使用しないようにしてください:

代わり
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ステートメントは、オブジェクトおよびリソースの解放の正しい処分を保証します。

忘れてしまった場合は、ガベージコレクタにクリーニングを残していますが、これには時間がかかることがあります。

+21

いずれのサンプルでも.Close()ステートメントは必要ありません。これは.Dispose()呼び出しによって処理されます。 –

+0

いいえ、コードに – Codebrain

+0

のオプションとして閉じるとマークしました。このサンプルは、閉鎖/廃棄される基底の接続を表示していません。これが最も重要なことです。 – Joe

9

安全のためには、すべてのSqlDataReaderオブジェクトをusing statementにラップしてください。

+0

フェア。しかし、使用しているステートメントがない場合は、実際にパフォーマンスに違いはありますか? –

+0

usingステートメントは、finallyセクションのclose/disposeメソッドを使用して、try..finally ...ブロックにDataReaderコードをラップするのと同じです。基本的には、オブジェクトが適切に処分されることを「保証」するだけです。 – Todd

+0

これは私が提供したリンクからまっすぐです: "usingステートメントは、オブジェクト上のメソッドを呼び出す際に例外が発生してもDisposeが呼び出されることを保証します。" – Kon

4

"using"ステートメントでSQLDataReaderをラップするだけです。それはあなたの問題の大部分を処理する必要があります。

40

SqlCommand.ExecuteReader()を使用してインスタンス化されたSqlDataReaderを廃棄すると、ではなく、が基になる接続を閉じる/破棄することに注意してください。

一般的なパターンは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を使用して開かれていることが重要です。これにより、リーダーのクローズ/ディスポジションによって基底の接続が閉じられます。パターンは、このようなものになります。

と、呼び出し元のコードをちょうどので、読者を配置する必要があります。十分な

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

SqlCommandオブジェクトにClose()メソッドはありません。 – Dave

+0

メソッドがSqlDataReaderを返す2番目のコードスニペットでは、コマンドは破棄されません。それは大丈夫ですか?コマンドを破棄(使用ブロックで囲んでください)してからリーダーを返すのは大丈夫ですか? – alwayslearning

+0

@alwayslearningこれはまさに私が持っているシナリオです...... SqlDataReaderを呼び出し元に返すときにSqlCommandを閉じたり破棄したりできますか? – ganders