2013-06-07 7 views
18

SqlConnectionSqlCommandおよびSqlDataReaderはすべてIDisposableインターフェイスを実装しています。私は常にIDisposablesusingブロックにラップするベストプラクティスについて読んでいます。SqlConnection SqlCommand SqlDataReader IDisposable

ので、データを照会するための私の一般的なシナリオは、(当然の大きな文脈でlinq2sqlのようなマッピングツールが適しているだろうが、ちょうど私たちはここに、このアプローチを使用したいと仮定します)、このようになります:

using (SqlConnection cn = new SqlConnection("myConnectionstring")) 
{ 
    using (SqlCommand cm = new SqlCommand("myQuery", cn)) 
    { 
     // maybe add sql parameters 
     using (SqlDataReader reader = cm.ExecuteReader()) 
     { 
      // read values from reader object 
      return myReadValues; 
     } 
    } 
} 

これは正しい方法ですか、それは過剰殺害と見なすことができますか?私はusingブロックを入れ子にしてこのレベルについて少しは確信していますが、もちろん私は正しい方法でそれをやりたいのです。 ありがとう!

答えて

15

へのSqlConnection、SqlCommandオブジェクトとSqlDataReaderのをラップすることができますブロックし、私は専門家ではないが、私は使用しては/最後に試しに翻訳されていることを知っています正しい方法。あるクラスがIDisposableを利用する場合は、ステートメントにラップして、Dispose()メソッドが呼び出されるようにする必要があります。さらに、そのようなSQL Serverで管理されていない外部の技術との通信は、軽く取られるべきではありません。 SqlCommandオブジェクトは非常に良い理由でIDisposableを実装しています。以下のコードはSqlCommandオブジェクトのDispose()方法です:

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     this._cachedMetaData = null; 
    } 
    base.Dispose(disposing); 
} 

、あなたが見ることができるように、それはあまりにもクリーンアップを取得することができるよう_cachedMetaDataオブジェクトへの参照を解放します。

+0

あなたの答え、特に 'SqlCommands'の処理に関する詳細については、ありがとう - ちょうど私が探していた情報! –

+0

@ Chips_100、私は助けになることができてうれしいです! –

+0

ちょうどFYIの "using"はtry - > finallyブロックの構文的な砂糖で、最終的にDisposeを呼び出します。しかし、そのようにはしないでください - usingキーワードを使用してください。 :) – Haney

-1

SqlCommandの処理には何の問題もありません。 SqlConnectionSqlDataReaderは処分する必要があります。

SqlConnectionは、範囲外になると自動的に閉じないためです。

SqlDataReaderは、リーダーが閉じられるまでSqlConnectionをビジー状態に保つことができます。

MSDNの例でさえ、SqlCommandを処理していません。

+0

Huh?それはIdisposableを実装しているので、処分されるだろう。 GCが起動するまで(なぜなら)、浮動しているのはなぜですか? –

+0

「IDisposable」を実装するクラスインスタンスを破棄するのがベストプラクティスとして広く受け入れられています。問題は、なぜ 'SqlCommand'を処分するのではなく、なぜそうしないのでしょうか? –

+0

私は、重要ではない他のものを手に入れることよりもそれほど重要ではないことを指摘しています。 @ TonyHopkinson、あなたが作成するすべてのオブジェクトが範囲外になった後、GCを実行しますか?いいえ?ポイントがないので。 Disposeはクロックサイクルも使用します。あなたは一般的にガベージコレクションに反対するか、まったく論議してはいけません。 – SamiHuutoniemi

-2

多分あなたはこれが100でユニークなのtry /ついに

try { 
    // code here with SqlConnection, SqlCommand and SqlDataReader 
} 
finally 
{ 
    // Dispose call on SqlConnection, SqlCommand and SqlDataReader 
} 
+0

私はあなたをマークしていませんでしたが、これを試してはいけません。これは同等ではなく、例外が発生した場合には、ふるいのように漏れて、さらに多くの例外を発生させる可能性があります。 –

+0

@TonyHopkinson私はちょうどフィードバックがあると答えました。なぜそれが同等でないのかさらに説明できますか?どうもありがとうございました! –

+1

sql connection connectが例外を発生させる場合。最後に実行され、sqlコマンドでnull参照例外が発生します。ラウンドを取得するには、無条件でテストする必要があります。 –

1

はい、正しいです。ネストされた中括弧が1つのステートメントであるので、それを見逃すことができますが、それが読みやすさに加わるとは思いません。

1

これは過剰です。 usingブロックは、例外がスローされたとしてもオブジェクトのDispose()メソッドが確実に呼び出されるため、良い方法です。

しかし、この種の名前があります。 コードの砂糖と呼ばれています。

using (foo bar = new foo()) { //...snip } 

がための短い手のコードです::だから、どちらのフォームは、他のと同じである

foo bar = null; 
Exception error = null; 
try { 
    bar = new foo(); 
    // ...snip 
} 
catch (Exception ex) { 
    error = ex; 
} 
finally { 
    if (bar != null) bar.Dispose(); 
    if (error != null) throw error; 
} 

、彼らは同じことを記述するだけで、さまざまな方法です。言い換えれば、forwhileの間の同じ差異:基本的に同じことをしますが、異なる方法で使用されます。

usingは、コードが短く読みやすくなり、処理が自動化されるので、これが望ましいです。あなたがそれを使用する必要があるかどうかに関しては、あなたが言うべき人に耳を傾けないでください常に何かを行う。これは、許可された良い習慣、ですが、人々はあなたがべきと言うのでものを使用して使用して、またはないのとメリットと結果を使用する理由を使用する際を知ることは何かをより方法がより価値があります。

編集:エレンの答えはあなたがreaderためusingのブロックを持っているのは嫌だ場合の例があります。

+1

'finally'ブロックを持っている場合、' catch'ブロックは必要ありません... – Alxandr

3

これは正しい方法です。読者がこれをやることになります。場合によっては、読者が開いたままにしておく必要があります(恐らく、あなたのメソッドを返します)ので、すぐに読者を処分することはできません。そのような場合は、あなたを助けることができるのExecuteReaderのオーバーロードがあります:

var cn = new SqlConnection("myConnectionstring"); 
var cm = new SqlCommand("myQuery", cn); 
var reader = cm.ExecuteReader(CommandBehavior.CloseConnection); 
return reader; 

これは、接続して、読者のオープンを維持します。読者が一旦閉鎖/処分されると、読者は接続も閉じて(処分する)。

using(var reader = GetReader()) //which includes the code above 
{ 
    ... 
} // reader is disposed, and so is the connection. 
+0

'' GetReader'の例は、 'new SqlCommand'または' ExecuteReader'がスローするときにコネクションを破棄しないので、欠陥があります。より完全な実装については、次の回答を参照してください。http://stackoverflow.com/a/744307/13087 – Joe

+0

@Joe良い点ですが、これは完全な実装ではありません(リンクありがとう)。私が指摘したいのは、読者が開いたままにする必要があるときに 'CommandBehavior.CloseConnection'を使うことでした。 –

5

あなたが左にコード近づくためにタイポグラフィの以下の方法を使用することができます。

using (SqlConnection cn = new SqlConnection("myConnectionstring")) 
using (SqlCommand cm = new SqlCommand("myQuery", cn)) 
using (SqlDataReader reader = cm.ExecuteReader()) 
{ 
    // read values from reader object 
    return myReadValues; 
} 

が他のとおり、既に指摘し、しかし正しいネストされた3個のusingブロックを使用します。

+0

後でコードの残りの部分(つまり、Visual StudioでCtrl + K + D)を自動識別すると、その部分は失われます。 – Renan

+0

ありがとう、私は前に宣言を「積み重ねる」ことを知らなかった。 SqlCommandにパラメータを追加する必要がある場合は、それを使用することはできません。情報をもう一度ありがとう! –

+1

@Renan実際に私はVS2012でそれを失うことはありません。私が正しく覚えていれば、VS2010はこの「スタック使用」もサポートしていました... –

関連する問題