|
2016/06/08(Wed) 18:37:55 編集(投稿者)
■No80068 (WAN さん) に返信 > For Each row As DataRow In rs.Rows
この rs が DataTable だとしたら NG です。 DataTable には「削除したレコード」も含まれていることに注意してください。
'[VB6] rs.Delete v = rs.Collect(columnName) '削除済みレコードへの操作はエラーになる
'[.NET] dataTable1.Rows(0).Delete() 'Rows(0) が新規行ではなく既存行だった場合 v = dataTable1.Rows(0)(columnName) 'DeletedRowInaccessibleException の例外になる
BindingSource や DataView などを通じてアクセスするようにすれば、 削除行を取り除いた有効行に対しての For Each が可能になります。
> (データベースをEOFまでループさせたい)
ADODB の Recordset は「カーソル位置の行」しかアクセスできず、 MoveNext 等を通じてカーソル位置を変更する必要がありました。
一方、DataTable の場合は .Rows(行番号)(列番号) などでアクセスできるため For や For Each でも処理しやすくなっています。その点の認識はあっていると思います。
> しかし、VB6ではEOFやMoveNextなどは無くなったと聞いております。
VB6では引き続き使うのでは…? (おっと、修正されていますね)
> しかし、VB.NETではEOFやMoveNextなどは無くなったと聞いております。
ADODB の MoveNext による順次検索に相当するのは、 ADO.NET では DataReader クラスです。 '[.NET] Dim reader = command.ExecuteReader() If reader.HasRows Then Do While reader.Read() Console.WriteLine(reader(0) & vbTab & reader(1)) Loop End If
これは、ADODB でいうところのファイアホースなカーソルモードであり、 adUseServer, adOpenForwardOnly, adOpenReadOnly に相当します。
読み取りのみの順次処理であれば、DataReader を使うのが良いと思います。
一方、ADO.NET での DataTable というのは、 ADODB でいうところの『切断型 Recordset』に相当します。 すなわち、メモリ上にデータをまとめて読み込んでおき、 それを編集してから、更新した差分をデータベースに書き戻す方式です。
『切断型 Recordset』には馴染みが無いかもしれないので補足すると、 最初に、静的なスナップショットとしてデータのコピーを取得し、
'[VB6] rs.CursorLocation = adUseClient 'カーソルモードが肝 rs.Open query, conn, adOpenStatic, adBatchOptimistic Set rs.ActiveConnection = Nothing conn.Close
切断後にクライアント側で編集・追加(AddNew)・削除(Delete)を行った後、
'[VB6] conn.Open Set rs.ActiveConnection = conn rs.UpdateBatch '※バッチ更新対応の OLE DB Provider が必要
として、再接続後に更新内容をデータベースに事後反映させる手法です。 (このモードでは、Filter プロパティや Sort プロパティなども使えます)
ADO.NET における DataSet や DataTable は、これと同様の仕組みです。 まずは DataAdapter を通じて、更新・参照対象のデータ群を取得します。
'[.NET] Dim ds As New DataSet() Dim adapter As New 何某DataAdapter(query, connection) adapter.Fill(ds, "Table1") Dim table1 As DataTable = ds.Tables("Table1")
そして、取得したデータの Rows に対して編集あるいは 追加(.Rows.Add/InsertAt)や削除(.Delete)を行い、最後に
adapter.Update(table1)
として、更新内容をデータベースに事後反映させます。 データを取得してから反映させるまでの間、 つまりデータを閲覧・編集している間は、 データベースと接続し続けておく必要はありません。
> また、EOFに到達しましたというIF文を書くにはどのようにすれば良いのでしょうか。
For Each 以外のアクセス方法が必要と言うことでしょうか。 であれば、.Rows.Count で行数を得られますので、For ループで処理できます。
'[.NET] For r = 0 To dataTable1.Rows.Count - 1 Dim currentRow = dataTable1.Rows(r) Debug.Print(currentRow(0) & vbTab & currentRow(1)) Next
どうしても Do ループ形式の列挙が良いのなら、お奨めはしませんが IEnumerator を使う手はあります。(一般的な方法ではありません)
'[.NET] Dim rs = dataTable1.Rows.GetEnumerator() Do While rs.MoveNext() Dim currentRow = rs.Current Debug.Print(currentRow(0) & vbTab & currentRow(1)) Loop
|