行のセットに対するデータ操作

Priya Singh
Microsoft Developer Network

2001 年 5 月

要約: この記事では、ADO.NET を使用して単一行エンティティを返すデータ操作について説明します。これは、Microsoft .NET Framework SDK および Visual Studio.NET のベータ 1 に準拠しています。

「.NET による分散アプリケーションの構築」の完全なサンプル コードは、MSDN Online Code Center からダウンロードまたは閲覧してください。

この記事で説明されている例を見るには、直接、BDAdotNetData3.vb をご覧ください。

「.NET による分散アプリケーションの構築」のサンプル コードをダウンロードする。(50 KB)

目次

  • はじめに

  • 読み取り操作

    • ADO.NET DataReader オブジェクトを使用する
    • ADO.NET DataSetCommand オブジェクトを使用する
  • 書込み操作

    • ADO.NET DataSetCommand オブジェクトを使用する
    • 挿入
    • 更新
    • 削除
  • 結論

  • はじめに

    ADO.NET は、データ行のセットへのアクセスを可能にする複数の機能を提供します。この記事では、データ ソースの行のセットにアクセスするための技法と、変更をデータ ソースにコミットする操作の例を示します。この記事のコード サンプルは、SQL マネージド プロバイダを使用して SQL Server データベースに接続しますが、ADO マネージド プロバイダにも適用されます。

  • 読み取り操作

    行のセットを返すクエリからの出力は、ADO.NET DataReader オブジェクトまたは DataSet オブジェクトを使用して返すことができます。

    • ADO.NET DataReader オブジェクトを使用する

      DataReader オブジェクトは、データを取得するための単純なメカニズムを提供します。DataReader オブジェクトによって、アプリケーション コードはデータのレコードを一度に 1 つずつ前方のみで読み取ることができます。

      DataReader オブジェクトの Read メソッドを使用すると、結果セット内の複数の行を読み取ることができます。このメソッドは、ポインタを次の行へ進めます。

      データが取得されるとき、ポインタは結果セットの最初の行に位置付けられているわけではないので、DataReader オブジェクトの反復を開始する前に、DataReader オブジェクトに対して Read メソッドを明示的に呼び出す必要があります。

      次のコード例では、データベースの Orders テーブルからすべての注文を取得して、DataReader オブジェクトを通じて読み取ります。

    Dim sqlConn As SQLConnection
    Dim sqlCmd As SQLCommand
    Dim outString As String
    Try
       'データベースへの接続を行う
       sqlConn = New SQLConnection(myConnString)
       'Command オブジェクトを生成する
       sqlCmd = New SQLCommand()
       'ストアド プロシージャを呼び出すための準備を行う
       With sqlCmd
          .CommandType = CommandType.StoredProcedure
          .CommandText = "GetOrderHeaders"
          .ActiveConnection = sqlConn
       End With
       'データベースとの接続を開く
          SQLConn.Open()
          'コマンドを実行し、結果セットを取得する
          sqlCmd.Execute(rowReader)
          '結果セットに含まれる行を走査する
       While (rowReader.Read)
        outString = rowReader.Item("OrderId").ToString() & "," & _
    		      rowReader.Item("CustomerId").ToString()
       End While
       'DataReader を閉じる
       rowReader.Close()
    Catch
    ' 例外処理
    …
    Finally
       '接続を閉じる
       sqlConn.Close()
    End Try
    

完全な BDAdotNetData3.vb サンプル コードの例 1 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

  • ADO.NET DataSetCommand オブジェクトを使用する

    DataSetCommand オブジェクトは、データ ソースと DataSet オブジェクトの間のマッピング層の役目を果たします。データ ソースからデータを取得して、DataSet オブジェクトにポピュレートし、変更をデータ ソースに送り返します。

    次の例では、データベースの Orders テーブルからすべての注文を取得します。データは、DataSet オブジェクト内のテーブルに取得されます。

    Dim sqlConn As SQLConnection
    Dim sqlDSCmd As SQLDataSetCommand
    Dim resultDataSet As DataSet
    Try
       'データベースへの接続を行う
       sqlConn = New SQLConnection(myConnString)
       'Commandオブジェクトを生成する
       sqlCmd = New SQLCommand()
       '新しい DataSet を生成する
       resultDateSet = New DataSet()
       'ストアドプロシージャを呼ぶための準備をする
       With sqlDSCmd
          With .SelectCommand
             .CommandType = CommandType.StoredProcedure
             .CommandText = "GetOrderHeaders"
             .ActiveConnection = sqlConn
       End With
    '返されたデータから DataSet を生成する
    .FillDataSet(resultDataSet, "Orders")
       End With
    Catch
       '例外処理
       …
    End Try
    

完全な BDAdotNetData3.vb サンプル コードの例 2 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

FillDataSet メソッドを呼び出すまでは、DataSet オブジェクトに Orders テーブルはないので、SQLDataSetCommand オブジェクトは DataSet オブジェクトのためにテーブルを自動的に作成して、返されたデータを入れます。FillDataSet メソッドを実行する前にテーブルを作成した場合は、SQLDataSetCommand オブジェクトは既存のテーブルにデータを入れるだけです。

'Booksテーブルの DataSet における行の数を調べる
nRows = resultDataSet.Tables("Orders").Rows.Count
'DataSet 行の値を取得する
For count = 0 To nRows -1
   System.Console.WriteLine(resultDataSet.Tables("Orders") _
         .Rows(count).Item("OrderId").ToString())
Next
  • 書き込み操作

    ADO.NET DataSetCommand オブジェクトと DataSet オブジェクトによって、データベース内のデータの取得、操作、および更新が可能です。新しい行の挿入、既存の行の更新、または既存の行の削除によって、DataSet オブジェクト内のテーブルを更新することができます。その後、DataSetCommand オブジェクトを使用して、DataSet テーブルに加えた更新をデータベースに送信することができます。

    • ADO.NET DataSetCommand オブジェクトを使用する

      DataSetCommand オブジェクトの Update メソッドは、DataSet オブジェクトにキャッシュされた変更をデータ ソースにサブミットします。DataSetCommand オブジェクトは、新しい行をサブミットするには InsertCommand を、変更された行をサブミットするには UpdateCommand を、データベースから行を削除するには DeleteCommand を使用します。

      DataSetCommand オブジェクトの InsertCommandUpdateCommand、および DeleteCommand プロパティを指定した場合、Update メソッドは、DataSet オブジェクト内の挿入、更新、または削除された行のそれぞれについて、Insert、Update、または Delete コマンドを実行します。そうでない場合は、Update メソッドは ForceGenerateUpdate というメソッドを呼び出して、InsertUpdate、および Delete コマンドを自動生成します。Update メソッドを呼び出すと、DataSetCommand オブジェクトは変更された行を調べて、その行の保留中の変更をサブミットするために、どの DataCommand オブジェクトを実行するかを判断します。

      望ましいのは、独自の InsertCommandDeleteCommand、または UpdateCommand を完全に指定することです。そうすれば、更新方法を明示的に制御することができ、自動生成よりもパフォーマンスが向上します。

    • 挿入

      DataSet オブジェクトに新しい行を挿入して、その変更をデータ ソースと調整することができます。InsertCommand プロパティを指定しなかった場合、DataSetCommand オブジェクトは Insert コマンドを自動生成して、新しい行をデータベースに挿入します。

      自動生成された Insert コマンド

      次のコード例では、データベースの Orders テーブルからすべての注文を取得します。データは、DataSet オブジェクト内のテーブルに取得されます。DataSet オブジェクトにいくつかの行を追加して、その変更をデータベースへ反映させるために SQLDataSetCommand オブジェクトの Update メソッドを使用します。

    Dim sqlConn As SQLConnection
    Dim sqlDSCmd As SQLDataSetCommand
    Dim resultDataSet As DataSet
    Dim workRow As DataRow
    Try
       'データベースへの接続を行う
       sqlConn = New SQLConnection(myConnString)
       'Command オブジェクトを生成する
       sqlCmd = New SQLCommand()
       '新しい DataSet を生成する
       resultDateSet = New DataSet()
       'ストアド プロシージャを呼び出すための準備を行う
       With sqlDSCmd
          With .SelectCommand
             .CommandType = CommandType.StoredProcedure
             .CommandText = "GetOrderHeaders"
             .ActiveConnection = sqlConn
       End With
    '返されたデータから DataSet を取得する
    .FillDataSet(resultDataSet, "Orders")
       End With
    Catch
       '例外処理
       …
    End Try
    

完全な BDAdotNetData3.vb サンプル コードの例 3 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

FillDataSet メソッドを呼び出すまでは、DataSet オブジェクトに Orders テーブルはないので、SQLDataSetCommand オブジェクトは DataSet オブジェクトのためにテーブルを自動的に作成して、返されたデータを入れます。FillDataSet メソッドを実行する前にテーブルを作成した場合は、SQLDataSetCommand オブジェクトは既存のテーブルにデータを入れるだけです。

'新しい行(row)を作成する
workRow = resultDataSet.Tables("Orders").NewRow
'生成した行に対して列(column)の値を与える
workRow.Item("CustomerId") = 1
workRow.Item("OrderDate") = Now()
…
…
'DataSet に行を追加する
resultDataSet.Tables("Orders").Rows.Add(workRow)
'DataSet に他の行を追加する
workRow = resultDataSet.Tables("Orders").NewRow
'新しい行の列(column)に値を与える
workRow.Item("CustomerId") = 2
workRow.Item("OrderDate") = Now()
…
…
'DataSet に行を追加する
resultDataSet.Tables("Orders").Rows.Add(workRow)
'データソースに変更を反映させる
sqlDSCmd.Update(resultDataSet, "Orders")

SQLDataSetCommand オブジェクトの InsertCommand プロパティは指定されなかったので、SQLDataSetCommand オブジェクトは、Update メソッドが呼び出されたときに指定された Select コマンドに基づいてステートメントを自動生成します

InsertCommand プロパティを使用する

SQLDataSetCommand オブジェクトに対して Update メソッドが呼び出されるときに実行される独自の INSERT ステートメントを指定するには、InsertCommand プロパティを設定します。SQLDataSetCommand オブジェクトは、指定された Insert コマンドを実行して、データベースに行を挿入します。パラメータ化された Insert クエリまたはストアド プロシージャを使用して、InsertCommand プロパティを設定することができます。

SQL マネージド プロバイダを使用するときには、パラメータ化クエリで名前付きパラメータを使用する必要があります。これとは違って、ADO マネージド プロバイダでパラメータを使用するときには、パラメータ マーカー '?' の付いた位置パラメータを使用します。

すべてのパラメータについて SourceColumn プロパティを設定する必要があります。SourceColumn プロパティは、テーブル内のどの列が値を提供するかを DataSetCommand オブジェクトに指示します。これを、実際のパラメータ名に設定します。

'select/insert コマンドを明示する
…
sqlDSCmd.SelectCommand.CommandText = "GetOrderHeaders"
'名前付きパラメータによって、insert クエリを生成
sqlDSCmd.InsertCommand.CommandText = "Insert Into Orders " & _
	"(CustomerId,OrderDate,ShipToName,ShipToAddressId,OrderStatus) " &  _
	"Values(@CustomerId,@OrderDate,@ShipToName,@ShipToAddressId,@OrderStatus)"
'返されたデータからDataSetを取得する
sqlDSCmd.FillDataSet(resultDataSet, "Orders")
'パラメータ化された insert ステートメントのパラメータを定義する
sqlDSCmd.InsertCommand.Parameters.Add _
	(New SQLParameter("@CustomerId",SQLDataType.Int))
'SourceColumn プロパティに値を与える
sqlDSCmd.InsertCommand.Parameters("@CustomerId").SourceColumn = _
	"CustomerId"
sqlDSCmd.InsertCommand.Parameters.Add _
	(New SQLParameter("@OrderDate",SQLDataType.DateTime))
'SourceColumn プロパティに値を与える
sqlDSCmd.InsertCommand.Parameters("@OrderDate").SourceColumn = _
	"OrderDate"
…

完全な BDAdotNetData3.vb サンプル コードの例 4 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

同じ手順に従って、新しい行をテーブルに追加します (「自動生成された Insert コマンド」のセクションを参照)。

'データソースへ変更を反映させる
sqlDSCmd.Update(resultDataSet, "Orders")
  • 更新

    DataSet オブジェクト内の行を更新して、その変更をデータ ソースと調整することができます。UpdateCommand プロパティを指定しなかった場合、DataSetCommand オブジェクトは Update コマンドを自動生成して、データベース内の行を更新します。

    自動生成された Update コマンド

    次のコード例では、データベースの Orders テーブルからすべての注文を取得します。データは、DataSet オブジェクト内のテーブルに取得されます。DataSet オブジェクト内のいくつかの行を更新して、その変更をデータベースへ反映させるために SQLDataSetCommand オブジェクトの Update メソッドを使用します。

Dim sqlConn As SQLConnection
Dim sqlDSCmd As SQLDataSetCommand
Dim resultDataSet As DataSet
Dim workRow As DataRow
Try
   'データベースへの接続を開く
   sqlConn = New SQLConnection(myConnString)
   'Command オブジェクトを生成する
   sqlCmd = New SQLCommand()
   '新しい DataSet を生成する
   resultDateSet = New DataSet()
   'ストアド プロシージャを呼び出すための準備をする
   With sqlDSCmd
      With .SelectCommand
         .CommandType = CommandType.StoredProcedure
         .CommandText = "GetOrderHeaders"
         .ActiveConnection = sqlConn
   End With
'返されたデータからDataSetを生成する
.FillDataSet(resultDataSet, "Orders")
   End With
Catch
   '例外処理
   …
End Try

'テーブルの行を更新する
'"ShipToName" の値を新しい値とする
resultDataSet.Tables("Orders").Rows(0).Item("ShipToName") = "NewResident"
'テーブル上の他の行も更新する
'"ShipToAddress" に新しい値を与える
resultDataSet.Tables("Orders").Rows(1).Item("ShipToAddress") = "NewResident"
'データソースへ変更を反映させる
sqlDSCmd.Update(resultDataSet, "Orders")

完全な BDAdotNetData3.vb サンプル コードの例 5 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

UpdateCommand プロパティを使用する

SQLDataSetCommand オブジェクトに対して Update メソッドが呼び出されたときに実行される独自の UPDATE ステートメントを指定するには、UpdateCommand プロパティを設定します。この目的には、パラメータ化された Update クエリまたはストアド プロシージャを使用することができます。

パラメータ化クエリで定義されたパラメータのそれぞれについて設定する必要がある重要なプロパティが 2 つあります。それは、SourceColumnSourceVersion です。これらについて、以下に説明します。

With sqlDSCmd
   With .UpdateCommand
      .CommandType = CommandType.Text
      '名前付きパラメータによって、Update クエリを定義する
      .CommandText = "Update Orders Set CustomerId=@CustomerId," & _
                     "ShipToName=@ShipToName" & _
                     "Where OrderId=@OldOrderId"
      .ActiveConnection = New SQLConnection(myConnString)
   End With
End With
'Update ステートメントのパラメータを定義する
sqlDSCmd.UpdateCommand.Parameters.Add _
      (New SQLParameter("@CustomerId",SQLDataType.Int))
'SourceColumn プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@CustomerId").SourceColumn = _
		"CustomerId"
'SourceVersion プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@CustomerId").SourceVersion = _
		DataRowVersion.Current
sqlDSCmd. UpdateCommand.Parameters.Add _
		(New SQLParameter("@ShipToName",SQLDataType.NvarChar, 40))
'SourceColumn プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@ShipToName").SourceColumn = _
		"ShipToName"
'SourceVersion プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@ShipToName").SourceVersion = _
		DataRowVersion.Current
sqlDSCmd. UpdateCommand.Parameters.Add _
		(New SQLParameter("@ShipToAddress",SQLDataType.NvarChar, 100))
'SourceColumn プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@ShipToAddress").SourceColumn = _
		"ShipToAddress"
'SourceVersion プロパティを定義する
sqlDSCmd. UpdateCommand.Parameters("@ShipToAddress").SourceVersion = _
		DataRowVersion.Current

完全な BDAdotNetData3.vb サンプル コードの例 6 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

SourceColumn は、テーブル内のどの列が値を提供するかを DataSetCommand オブジェクトに指示します。これを設定するには、テーブル内の列の名前を代入します。UpdateCommand は、更新の際に SourceVersion プロパティを使用して、パラメータ値として元の値と現在の値のどちらが使用されるかを判断します。このため、主キーの更新が可能です。InsertCommandDeleteCommand は、このプロパティを無視します。

たとえば、主キーを 5 から 15 に変更する場合は、「主キーが 5 である行を、主キー 15 を持つように更新せよ」と指示しなければなりません。したがって、このためには、次のようなパラメータ化クエリの場合、

"Update myTable Set colPrimary=@colPrimary Where colPrimary=@oldcolPrimary"

@oldcolPrimary パラメータの SourceVersion プロパティを DataRowVersion.Original に設定します。

「自動生成された Insert コマンド」のセクションの説明と同じステップに従って、行を更新します。

'DataSet の行を更新する
sqlDSCmd.Update(resultDataSet, "Orders")
  • 削除

    DataSet オブジェクト内の行を削除して、その変更をデータ ソースと調整することができます。DeleteCommand プロパティを指定しなかった場合、DataSetCommand オブジェクトは Delete コマンドを自動生成して、データベース内のテーブルから行を削除します。

    自動生成された Delete コマンド

    次のコード例では、データベースの Orders テーブルからすべての注文を取得します。データは、DataSet オブジェクト内のテーブルに取得されます。DataSet オブジェクトからいくつかの行を削除して、その変更をデータベースへ反映させるために SQLDataSetCommand オブジェクトの Update メソッドを使用します。

Dim sqlConn As SQLConnection
Dim sqlDSCmd As SQLDataSetCommand
Dim resultDataSet As DataSet
Dim workRow As DataRow
Try
   'データベースへの接続を行う
   sqlConn = New SQLConnection(myConnString)
   'Command オブジェクトを生成する
   sqlCmd = New SQLCommand()
   '新しい DataSet を生成する
   resultDateSet = New DataSet()
   'ストアド プロシージャを呼び出すための準備を行う
   With sqlDSCmd
      With .SelectCommand
         .CommandType = CommandType.StoredProcedure
         .CommandText = "GetOrderHeaders"
         .ActiveConnection = sqlConn
   End With
'返されたデータからDataSetを生成する
.FillDataSet(resultDataSet, "Orders")
   End With
Catch
   '例外処理
   …
End Try


'Orders テーブルの DataSet から、いくつからの行を削除する
resultDataSet.Tables("Orders").Rows(0).Delete()
resultDataSet.Tables("Orders").Rows(1).Delete()
'データベースへの変更を反映させる
sqlDSCmd.Update(resultDataSet, "Oders")

完全な BDAdotNetData3.vb サンプル コードの例 7 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

DeleteCommand プロパティを使用する

SQLDataSetCommand オブジェクトに対して Update メソッドが呼び出されたときに実行される独自の DELETE ステートメントを指定するには、DeleteCommand プロパティを設定します。この目的には、パラメータ化された Delete クエリまたはストアド プロシージャを使用することができます。

すべてのパラメータについて SourceColumn プロパティを設定する必要があります。SourceColumn は、テーブル内のどの列が値を提供するかを DataSetCommand オブジェクトに指示します。これを実際のパラメータ名に設定します。

'DeleteCommand を明示する
With sqlDSCmd
   With .DeleteCommand
      .CommandType = CommandType.Text
      '名前付きパラメータによって、Delete クエリを定義する
      .CommandText = "Delete from Orders Where OrderId=@OrderId"
      .ActiveConnection = New SQLConnection(myConnString)
   End With
End With
'Delete ステートメントのパラメータを定義する
sqlDSCmd.DeleteCommand.Parameters.Add _
      (New SQLParameter("@OrderId",SQLDataType.Int))
'SourceColumn プロパティを設定する
sqlDSCmd.DeleteCommand.Parameters("@OrderId").SourceColumn = "OrderId"
'Orders テーブルの DataSet から、いくつかの行を削除する
resultDataSet.Tables("Orders").Rows(2).Delete()
resultDataSet.Tables("Orders").Rows(10).Delete()
'データベースへ変更を反映させる
sqlDSCmd.Update(resultDataSet, "Orders")

完全な BDAdotNetData3.vb サンプル コードの例 8 を参照してください (ダウンロードについては、この記事の始めを参照してください)。

  • 結論

    ADO.NET は、データ行のセットへのアクセスを可能にする豊富な機能を提供します。.NET Framework は、データ行のセットを読み取るための DataReaderDataSet、および DataSetCommand オブジェクトを提供します。データ ソースが SQL Server 2000 の場合は、データ行のセットを XML として返すというのも、もう 1 つの実際的な方法です。