19

SqlConnectionSqlCommandおよびSqlDataReaderすべてがインターフェイスを実装しIDisposableます。常にブロックにラップIDisposablesするベスト プラクティスについて読みました。using

したがって、データをクエリするための私の一般的なシナリオは次のようになります (より大きなコンテキストでは、もちろん 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が、もちろん正しい方法でやりたいと思っています。ありがとう!

4

7 に答える 7

16

これは 100% 正しい方法です。クラスが活用する場合は、メソッドが確実に呼び出されるようにステートメントIDisposableでラップする必要があります。さらに、SQL Server のような管理されていない外部テクノロジとの通信を軽視すべきではありません。オブジェクトは非常に正当な理由で実装されています。以下のコードは、オブジェクトのメソッドです。usingDispose()SqlCommandIDisposableDispose()SqlCommand

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

ご覧のとおり、オブジェクトへの参照を解放して、_cachedMetaDataオブジェクトもクリーンアップできるようにしています。

于 2013-06-07T14:00:21.380 に答える
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ブロックを使用することは正しいです。

于 2013-06-07T14:15:52.253 に答える
4

リーダーを使いこなすのであれば、それが正しい方法です。場合によっては、リーダーを開いたままにしておく必要があるため (メソッドがそれを返す可能性があります)、リーダーをすぐに破棄してもうまくいきません。そのような場合、役立つ 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.
于 2013-06-07T14:12:20.173 に答える
1

そうです。ネストされた using の中括弧は 1 つのステートメントであるため、見逃す可能性がありますが、読みやすさが向上するとは思いません。

于 2013-06-07T14:00:42.923 に答える
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;
}

どちらの形式も同じですが、同じことを別の方法で書いているだけです。言い換えれば、 と の同じ違いfor:while基本的に同じことをしますが、異なる方法で使用されます。

usingコードが短くなり、読みやすくなり、破棄が自動化されるため、推奨されます。ただし、それを使用する必要があるかどうかについては、常に何かを行う必要があるという人々の意見に耳を傾けないでください。確かに良い習慣ですが、 をいつ使用するか、なぜ使用するか、何かを使用することの利点と結果、または使用しないことの利点を知ることは、人々があなたがすべきだと言うので何かをするよりもはるかに価値があります。

編集: Eren の回答にはusingreader.

于 2013-06-07T14:07:51.033 に答える
-1

を処分しても意味がありませんSqlCommand。ただし、SqlConnectionandSqlDataReaderは破棄する必要があります。

範囲外になると、SqlConnectionそれ自体が閉じないためです。

は、リーダーが閉じられるまでビジー状態SqlDataReaderを維持できます。SqlConnection

MSDN の例でさえ、SqlCommand.

于 2013-06-07T13:59:01.470 に答える
-2

私は専門家ではありませんが、using が try/finally ブロックに変換されることは知っています

try {
     // code here with SqlConnection, SqlCommand and SqlDataReader
}
finally
{
  // Dispose call on SqlConnection, SqlCommand and SqlDataReader
 }
于 2013-06-07T13:59:04.247 に答える