SqlDataAdapter

C# ADO.NET SqlDataAdapter によるストアドプロシージャ呼び出しで DataSet にデータを読み込む

前回は SqlDataReader を使って順方向専用のストリーム読み取りを行いました。今回は SqlDataAdapter を使用し、ストアドプロシージャの実行結果をまとめてDataSet(メモリ上のオフラインテーブル)へ格納します。DataGridView などのコントロールへデータバインドする場面でよく使われます。
SqlCommand(ストアドプロシージャ定義) → SqlDataAdapter.SelectCommandadapter.Fill(DataSet) でデータを自動取得

サンプルコード

string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();

    SqlCommand sqlCom = new SqlCommand();
    sqlCom.Connection = conn;
    sqlCom.CommandText = "myProc";
    // 実行種別をストアドプロシージャに指定
    sqlCom.CommandType = CommandType.StoredProcedure;

    // ストアドプロシージャへ入力パラメータを渡す
    SqlParameter param = new SqlParameter("@id", SqlDbType.Int, 8);
    param.Value = 4;
    param.Direction = ParameterDirection.Input;
    sqlCom.Parameters.Add(param);

    // データアダプター
    SqlDataAdapter sqlDA = new SqlDataAdapter();
    sqlDA.SelectCommand = sqlCom;

    DataSet ds = new DataSet();
    // データを読み込み、第2引数はDataSet内のテーブル名
    sqlDA.Fill(ds, "sdfdsf");

    // WinFormsグリッドコントロールへバインド
    this.dataGridView1.DataSource = ds.Tables[0];
}Code language: C# (cs)

より良い記述例

string connectionString = "Data Source=.;Initial Catalog=db;Integrated Security=SSPI;";
using (SqlConnection conn = new SqlConnection(connectionString))
{
    string procName = "myProc";
    using (SqlCommand sqlCom = new SqlCommand(procName, conn))
    {
        sqlCom.CommandType = CommandType.StoredProcedure;
        // パラメータを簡潔に設定
        sqlCom.Parameters.Add("@id", SqlDbType.Int).Value = 4;

        SqlDataAdapter sqlDA = new SqlDataAdapter(sqlCom);
        DataSet ds = new DataSet();
        // 結果セットを読み込み、テーブルに別名 ArticleResult を付ける
        sqlDA.Fill(ds, "ArticleResult");

        // コントロールへバインド
        dataGridView1.DataSource = ds.Tables["ArticleResult"];
        // インデックスによるアクセスも可:ds.Tables[0]
    }
}Code language: JavaScript (javascript)

解説

SqlDataAdapter.Fill() の仕様
  1. 接続の自動制御Fill実行時に接続がOpen()されていない場合、アダプターが内部で接続を開き、処理終了後自動で閉じます。

サンプルコードでは明示的にconn.Open()を呼んでいますが、必須ではありません。動作はします。

  1. Fill(ds, "テーブル名"):メモリ上に作成されるDataTableに名前を設定し、名前指定で参照できるようにします。省略すると既定でTableという名前になります。
  2. ストアドプロシージャが複数の結果セットを返す場合、Fillは複数のDataTableを自動生成します:ds.Tables[0]、ds.Tables[1]...
DataSet と SqlDataReader の主な違い
オブジェクト動作モード接続占有利用シーン
SqlDataReader接続保持型ストリーム読取DB接続を開いたまま維持大量データ、全キャッシュ不要、1行ごと処理
DataSet(DataAdapter)オフラインメモリキャッシュFill完了後接続を解放UIコントロールバインド、小規模データ、繰り返し参照

ストアドプロシージャ実行に必須の設定

sqlCom.CommandType = CommandType.StoredProcedure;

この1行が無いと、ADO.NETは myProc を普通のSQL文として解釈し実行し、エラーが発生します。

コントロールへのバインド

dataGridView1.DataSource = ds.Tables[0];

WinForms の DataGridViewDataTable を直接バインド可能で、カラムが自動生成されます。
データ変更後にデータベースへ反映したい場合は SqlDataAdapter.Update() を使って一括更新が行えます。

明示的に接続を Open しない書き方

using(SqlConnection conn=new SqlConnection(connectionString))
using(SqlCommand cmd=new SqlCommand("myProc",conn))
{
    cmd.CommandType=CommandType.StoredProcedure;
    cmd.Parameters.Add("@id",SqlDbType.Int).Value=4;
    SqlDataAdapter da=new SqlDataAdapter(cmd);
    DataSet ds=new DataSet();
    da.Fill(ds,"Article"); // 接続の開閉を自動処理
}Code language: JavaScript (javascript)

上記コードでは using 文で接続リソースを管理しています

SqlDataAdapter

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です