2009-07-21 2 views
5

ストアドプロシージャからレコードを照会するコードがありますが、私が必要としているものを廃棄していないか、オブジェクトがガベージコレクタによって後で削除されたときに処分していない可能性があります。c#sql何を処理するか

SqlDataReaderはtry catchブロック内にあるため、処理する必要がありますか?

cmd.Disposeとcmd.Connection.Closeの両方を実行する必要がありますか、または他のものを推測しますか?

ガベージコレクタは、最終的にこれらのオブジェクトをすべて処分しますか(タイムリーではないかもしれません)か、これらのオブジェクトはアンマネージドコードを使用している可能性があります。

public void GetData(string studentID) 
    { 
     SqlCommand cmd = new SqlCommand("sp_stored_proc", 
       new SqlConnection(Settings.Default.connectionString)) 
       { CommandType = CommandType.StoredProcedure }; 
     try 
     { 
      cmd.Connection.Open(); 
      cmd.Parameters.AddWithValue("@student_id", studentID); 
      SqlDataReader dr = cmd.ExecuteReader(); 

     //do something with the data 

      if (dr != null) 
       dr.Dispose(); 
     } 
     catch 
     { 
      //error handling 
     } 
     finally 
     { 
      if (cmd != null) 
      { 
       cmd.Dispose(); 
       cmd.Connection.Close(); 
      } 

     } 

    } 

答えて

16

データリーダーとコマンドを処理する必要があります。コマンドを処理する場合は、別途接続を閉じる必要はありません。あなたは理想的usingブロック使用して両方を行う必要があります:あなたは例外処理が必要な場合は

using (SqlCommand cmd = new...) 
{ 
    // do stuff 
    using (SqlDataReader dr = cmd.ExecuteReader()) 
    { 
     // do stuff 
    } 
} 

を使用して、ブロックの内部や周り別々にそれを行うません - usingといえDisposeコールに対する最終的には不要です。

+1

これを複数回アップヴォートすることができたら、私はそうするでしょう。 COME ON PEOPLE!ブロックの使用! –

+2

'SqlCommand'オブジェクトを破棄すると、' SqlConnection'が処理されません**。これはテストが非常に簡単です。 http://stackoverflow.com/questions/60919/is-sqlcommand-dispose-enough/60934#60934 – arcain

+0

私はコマンドを処理しても読者を処分する必要がありますか?私は接続を廃棄してもコマンドを破棄する必要がありますか?あなたはこれのどんな情報源にも私たちを紹介することができますか? – Lii

3

それはトライキャッチ ブロック内にあるので、私はSqlDataReaderの を配置する必要がありますか?

- はい、try catchの内部にあるので、disposeメソッドは呼び出されません。

cmd.Disposeとcmd.Connection.Closeの両方を実行する必要がありますか、または他のものを推測する必要はありますか?

- はい、両方を実行する必要があります。 Cmd.disposeを呼び出すと接続が閉じられません。

disposeメソッドは、プログラマがガベージコレクタによって直接管理されていないリソースをクリーンアップするために使用されるか、空き領域を確保するためにプログラムが使用された後にクリアされる必要があります。技術的には、GCが処分を処理するようにプログラムを設定することができますが、それは私が作成しないと仮定しています。特に、クラスを書くプログラマーがdisposeメソッドを公開しています。コマンドをusingステートメントに入れることは、コードが宣言スペースを離れるときに処分されることがわかっているので、おそらく最も簡単なルートです。

using (var connection = new Connection()) 
{ 
    using (var cmd = new Command()) 
    { 



    } 
} 
+0

"いいえ、cmd.disposeは接続を終了します" - 私は間違っていると思います。私が知る限り、コマンドに対するDisposeの呼び出しは、その接続とは関係ありません。 –

+0

@Kevin:リンク先の投稿は、*接続オブジェクトでDisposeを呼び出すと、同じオブジェクト上でcloseを呼び出します。 「コマンド」という単語はページに表示されません。 –

+0

私は二重チェックをしたときに投稿を誤読しました。あなたが正しい。 – kemiller2002

2

個人的には、あるメソッドにdisposeメソッドがある場合は、それが本来のメモリリークを防ぐために使用する価値があります。

3

あなたはこのようなものを使用する場合:

public void GetData(string studentID) 
{ 
    using (SqlConnection connection = new SqlConnection(Settings.Default.connectionString)) 
    { 
     connection.Open(); 

     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandType = CommandType.StoredProcedure; 
      command.CommandText = "sp_stored_proc"; 
      command.Parameters.AddWithValue("@student_id", studentID); 

      using (SqlDataReader dataReader = command.ExecuteReader()) 
      { 
       // do something with the data 
      } 
     } 
    } 
} 

を、あなたの使い捨てのオブジェクトのすべてが正しく配置されたのでしょう。 SqlConnection、SqlCommand、およびSqlDataReaderオブジェクト(使用ブロックが終了するときに実行する処理)でDispose()を呼び出すと、それらが正しく閉じられます。

さらに、この方法では、すべての変数のスコープが使用される場所に保持されます。

このアプローチの欠点は、try/catchを使用してエラー処理が必要な場合は、メソッド本体全体にラップするか、エラーの読み取りとは異なる方法で接続エラーを処理する必要があることです。 ..

1

短いストーリーを作るには。 IDisposableを実装する場合は、Disposeに電話する必要があります。

あなたはDispose内の1つのオブジェクトが別のオブジェクトにDisposeを呼び出すことを把握するために反射板を使用する場合でも、私はまだ、これは、いくつかの将来のリリースでを変更することができ、内部実装の詳細をあるいるので、両方のDisposeを呼び出すことをお勧めしますので、常に真実であることに頼るべきではありません。

だから、Dispose何かIDisposableです。

-4

Connectionを最初にConnection.Open()で開く必要があります。 はその後、近くSqlDataReaderのは、まず、すべての後に を読み取るために、このようなSqlDataReaderのような方法を使用して、近くに接続

あなたがそれを配置する「を使用して」キーワードを使用することができますが、それは実際には良いアイデア

ではありませんキーワード "using"はオブジェクトを自動的に破棄することです。 つまり、オブジェクトはdisposeメソッドを実現する必要があります

+0

-1ブロックの使用は悪い考えですか? –

+0

なぜこの使用法が悪い考えであるのかを詳しく説明してください。 – LOAS