C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: データベースに関するループ処理(EOFなど)


(過去ログ 136 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■80068 / inTopicNo.1)  データベースに関するループ処理(EOFなど)
  
□投稿者/ WAN (19回)-(2016/06/08(Wed) 17:04:51)

分類:[VB.NET/VB2005 以降] 

2016/06/08(Wed) 17:40:34 編集(投稿者)

失礼致します。

環境はVisual Studio 2012の環境下で、言語はVB2012、.netフレームワークは3.0です。

現在、VB6のソースをからVB2012へ更新するということを行っていますが

VB6ではデータベースに関して以下のような処理が行われていました。
(データベースをEOFまでループさせたい)

Do Until rs.EOF
   処理
   rs.MoveNext
Loop

しかし、VB.NETではEOFやMoveNextなどは無くなったと聞いております。

For Each row As DataRow In rs.Rows
   処理
Next

書き直す場合は上記のような処理で良いのでしょうか。
(あくまで調査した例がFor EachだっただけでFor Eachじゃないとダメということはなく、Do Untilのままでも可です)

また、EOFに到達しましたというIF文を書くにはどのようにすれば良いのでしょうか。

知恵をお借りできればと思います。
よろしくお願い致します。
引用返信 編集キー/
■80071 / inTopicNo.2)  Re[1]: データベースに関するループ処理(EOFなど)
□投稿者/ しま (110回)-(2016/06/08(Wed) 18:06:10)
No80068 (WAN さん) に返信
> 環境はVisual Studio 2012の環境下で、言語はVB2012、.netフレームワークは3.0です。

DBを使うのなら、DBの製品名、バージョン、エディションなども書くと読む人にとって親切です
又、アプリケーションの種類も書いてください。 (Windows フォーム、Web フォーム、など...)

> 現在、VB6のソースをからVB2012へ更新を行っています
>
> VB.NETではデータベースに関して以下のような処理が行われていました。
> (データベースをEOFまでループさせたい)
>
> Do Until rs.EOF
>    処理
>    rs.MoveNext
> Loop
>
> しかし、VB6ではEOFやMoveNextなどは無くなったと聞いております。
VB.NET と VB6 との書き間違い???

大雑把な言い方ですが、 VB6 でのレコードセットに相当するものが .NET では データーセットです
データーセットは扱いたいデーターのまとまりが入っているイメージです。
なので、 EOF による検査が必要ないのです

>
> For Each row As DataRow In rs.Rows
>    処理
> Next
>
> 書き直す場合は上記のような処理で良いのでしょうか。
処理の内容にもよりますが、そういう考えでもいいのではないでしょうか。
処理の内容によっては、ループで廻さなくても済む場合もあるでしょう。

> (あくまで調査した例がFor EachだっただけでFor Eachじゃないとダメということはなく、Do Untilのままでも可です)
> また、EOFに到達しましたというIF文を書くにはどのようにすれば良いのでしょうか。

上にも書きましたが、データーセットに読込んでしまえば、特に EOF の検査は必要ないのです

ところで rs.Rows の rs はデーターセットかデーターテーブルかのインスタンスでいいのですね?


引用返信 編集キー/
■80072 / inTopicNo.3)  Re[1]: データベースに関するループ処理(EOFなど)
□投稿者/ 魔界の仮面弁士 (748回)-(2016/06/08(Wed) 18:26:28)
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
引用返信 編集キー/
■80084 / inTopicNo.4)  Re[2]: データベースに関するループ処理(EOFなど)
□投稿者/ WAN (20回)-(2016/06/08(Wed) 22:34:34)
しまさん、 魔界の仮面弁士さん

レスありがとうございます。
レコードセットとデータセットの違いが分かりました。

レコードセットではEOFの考え方が必要だった理由が良く分かりました。

書き込んで頂いた内容を参考にがんばってみます。

ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -