SqlDataAdapterとSqlDataReader


130

DBからデータを取得するためのSqlDataAdapterとSqlDataReaderの違いは何ですか?

具体的には、長所と短所、速度、メモリパフォーマンスを調べています。

ありがとう

回答:


193

SqlDataReader:

  • 完了するまで接続を開いたままにします(閉じることを忘れないでください!)。
  • 通常、1回だけ繰り返すことができます
  • データベースに更新して戻すのにはそれほど役に立ちません

一方、それは:

  • 時間だけではなく、結果セット全体でメモリ内の1つのレコードを持っている(これはすることができHUGE
  • その1回の反復で取得できる速度とほぼ同じです
  • (最初のレコードが利用可能になったら)より早く結果の処理を開始できます。一部のクエリタイプでは、これも非常に重要な場合があります。

SqlDataAdapter / DataSet

  • データのロードが完了するとすぐに接続を閉じることができます。自動的に閉じることもできます
  • すべての結果はメモリで利用可能です
  • あなたはそれを必要なだけ何度でも繰り返すことができます、またはインデックスで特定のレコードを検索することさえできます
  • データベースに更新するための組み込みの機能があります

代償:

  • はるかに高いメモリ使用
  • すべてのデータが読み込まれるまで待ってから、データを使用します

したがって、実際にはそれはあなたが何をしているのかに依存しますが、私はデータセットでのみサポートされる何かが必要になるまでDataReaderを好む傾向があります。SqlDataReaderは、読み取り専用グリッドにバインドする一般的なデータアクセスの場合に最適です。

詳しくは、Microsoftの公式ドキュメントをご覧ください。


5
DataSetはメモリ内のデータストアですが、datareaderはデータを取得するための単なる媒体です。簡単に言うと、DataSetでLinqクエリを実行できますが、データリーダーでは実行できません。
Partha Choudhury

実際、少しだけコードを追加することで、データリーダーでlinqクエリ(または少なくとも1つのクエリ)を実行できます。反復子ブロックを使用して、while (reader.Read())ループ内のIDataRecordとしてDataReaderキャストを返します。
Joel Coehoorn、2009年

7
この答えは誤解を招くものです。SqlConnectionオブジェクトとSqlDataReaderオブジェクトを「using」ステートメントでラップすると(IDisposableであるため、いずれにせよ、そうする必要があります)、接続は自動的に閉じられます。また、SqlDataReaderでDataSetを使用できます。DataSet.Load(SqlDataReader)を呼び出すだけです。
RickNZ 2011

4
@RickNZステートメントを使用して物事をクローズすることを信頼するのは速すぎません。それらは、Close()メソッドではなく、オブジェクトのDispose()メソッドを呼び出します。私は、Disposeが実際にオブジェクトを閉じなかった少なくとも1つのケースに遭遇しました。usingブロック内にcloseメソッドの明示的な呼び出しを含めることが常に最善です。
Cdaragorn 2012年

5
@Cdaragorn MSDNのドキュメントでは、通常、Close()とDispose()についてはかなり明確です。たとえば、SqlConnectionの場合、ドキュメントでは、Close()とDispose()は機能的に同等であると述べています。私はClose()の呼び出しに異論はありませんが、Dispose()の呼び出しもすべてのIDisposableに対して存在する必要があります-そしてこれを行う最もクリーンな方法は、usingステートメントを使用することです。Dispose()がClose()を呼び出さないことがわかっている場合は、可能であれば、finallyブロック内でClose()を呼び出す必要があります(usingブロック内ではありません)(したがって、例外がある場合でも呼び出されます)。
RickNZ 2012年

17

その答えはかなり広い可能性があります。

基本的に、私が通常使用する決定に影響を与える私にとっての主な違いは、SQLDataReaderを使用すると、データベースからデータを「ストリーミング」することです。SQLDataAdapterを使用すると、データベースからデータを抽出して、それ自体をさらに照会できるオブジェクトにしたり、CRUD操作を実行したりできます。

データのストリームを使用すると、SQLDataReaderの方がはるかに高速ですが、一度に1つのレコードしか処理できません。SQLDataAdapterを使用すると、データベースからクエリに一致する行の完全なコレクションを取得して、コードを操作/パススルーできます。

警告: SQLDataReaderを使用している場合は、ALWAYS、ALWAYS、ALWAYSを使用して、SQLDataReaderで接続を開いたままにしているため、接続を閉じるための適切なコードを必ず記述してください。これを行わない場合、または結果の処理中にエラーが発生した場合に接続を閉じる適切なエラー処理を行うと、アプリケーションで接続リークが発生します。

私のVBを許してください。ただし、これはSqlDataReaderを使用するときに必要なコードの最小量です。

Using cn As New SqlConnection("..."), _
      cmd As New SqlCommand("...", cn)

    cn.Open()
    Using rdr As SqlDataReader = cmd.ExecuteReader()
        While rdr.Read()
            ''# ...
        End While
    End Using
End Using     

同等のC#:

using (var cn = new SqlConnection("..."))
using (var cmd = new SqlCommand("..."))
{
    cn.Open();
    using(var rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //...
        }
    }
}

目的がdbの選択クエリを使用してデータを取得することであり、別の行でのみこのデータにアクセスする場合、前の行に移動する場合など、SQLDatareaderを使用し、dtable.Load(rdr)を使用してデータテーブルにデータをロードできます。次に、このデータテーブル内を上下に参照します。DataAdapterの代わりにこのメソッドを使用できます...
変数

14

SqlDataAdapterは通常、DataSetまたはDataTableに入力するために使用されるため、接続が閉じられた後(切断されたアクセス)にデータにアクセスできます。

SqlDataReaderは高速転送専用の接続カーソルであり、DataSet / DataTableへの入力よりも一般的に高速になる傾向があります。

さらに、SqlDataReaderを使用すると、一度に1レコードずつデータを処理し、メモリにデータを保持しません。明らかに、DataTableまたはDataSetを使用すると、メモリ割り当てのオーバーヘッドが発生します。

データをメモリに保持する必要がない場合は、レンダリングのみのために、SqlDataReaderを使用してください。切断された方法でデータを処理する場合は、DataAdapterを選択して、DataSetまたはDataTableのいずれかを入力します。


10

データベースからメモリ内のDataSet / DataTableを作成する場合は、SqlDataAdapterを使用します。その後、接続を閉じる/破棄し、メモリ内でデータテーブル/セットを渡す柔軟性があります。次に、データを操作し、InsertCommand / UpdateCommandと組み合わせてデータアダプターを使用してDBに永続化します。

ビジネスロジックの周りにデータを渡すなどの柔軟性を必要とせずに、高速で低メモリのフットプリントデータアクセスが必要な場合は、SqlDataReaderを使用します。これは、一度にすべてのデータをメモリにロードするわけではないため、大量のデータをすばやくメモリ使用量が少ない状態で取得する場合に最適です。SqlDataAdapterアプローチでは、DataSet / DataTableにすべてのデータが入力されるため、多くの行と列があり、保持するには多くのメモリが必要になります。


0

Fill関数は内部でDataReaderを使用します。考慮事項が「どちらが効率的ですか」の場合、レコードごとにコレクションを生成するタイトループでDataReaderを使用すると、DataAdapter.Fillを使用する場合と同じシステムの負荷になる可能性があります。

(System.Data.dll、System.Data.Common.DbDataAdapter、FillInternal。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.