MENU > HOME VB.NET VB6 VBA ソフトウェア リンク サイト情報
VB.NET> VB.NET 突撃レポート > 1  2  3  4  5  6  7  8  9  10  11  12 
PART7: ADO.NETによるデータベースアクセス その1 (2002年3月24日)

いよいよデータベースへのアクセスです。

テスト環境として事前にこのようなMDBとテーブルを作成しておきました。
MDBファイル名: D:\Test.mdb
テーブル名: T_TEST
データ:
 
ID (数値型) NAME (文字列型)
1 パパ
2 ママ
3 み〜くん
4 え〜くん

ボタンを押したらこのMDB内のテーブルのNAMEフィールドの値を順にデバッグコンソールに出力するコードを作成します。
まずはVB6を使用して従来通りの方法でコーディングしてみます。
参照設定で Microsoft ActiveX Data Object 2.6 Library を追加します。
 
Private Sub Command1_Click()

    Dim oConn As ADODB.Connection
    Dim oRec As ADODB.Recordset

    Set oConn = New ADODB.Connection
    oConn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Test.mdb")
    Set oRec = oConn.Execute("SELECT * FROM T_TEST")
    While Not oRec.EOF
        Debug.Print CStr(oRec.Fields("ID").Value) & "," & oRec.Fields("NAME").Value
        oRec.MoveNext
    Wend
    oRec.Close
    Set oRec = Nothing
    oConn.Close
    Set oConn = Nothing

End Sub
早速このコードをVB.NETへとアップグレードしてみると、ADOのタイプライブラリが 2.6から2.7にバージョンアップされていること以外はほとんど変わりませんでした。
動作も問題ないようです。
これできちんと動作するのですから、今までどおりの手法で良いのではないかと考える方もいると思いますが、せっかく .NET環境を体験しようという趣旨でやっていますので、そうは言わずにいっしょに先へ進みましょう。

実は(ってのもおかしな表現だが)私自身、ADO.NETについて全く前知識がありません。
そこでまずはMSDNで ADO.NET の関連トピック、リファレンスを片っ端から読み進んでいくことにします。

最初は接続に関する情報を検索します。
「ADO.NET Connection」 とキーワードを入力してみると...。

まずは「ADO.NET 接続」というページがヒットしました。このページでは、
これ以後のセクションの内容として、Introduction to ADO.NET Connection Design Tools というタイトルで、「接続オブジェクトとその使用方法の概要を示します。」
とあります。
早速このトピックを開いてみると冒頭で、

ADO.NETでは 接続を管理するオブジェクトとして、
SQLServer 7.0 以降の場合は System.Data.SqlClientネームスペースの SqlConnection オブジェクト、
その他の OLEDBプロバイダの場合、SystemData.OleDb ネームスペースの OleDbConnection オブジェクト
を使用します。


と書かれています。

あえて SQL Server と他のプロバイダを別々のオブジェクトで管理する理由は何なのでしょう?
実は SqlConnection オブジェクトは MSの自社製品であるRDBMS(SQL Server)をより高いパフォーマンスで使用できるように実行を最適化し、さらに OLEDB 層をバイパスしているという代物なのです。
他のベンダーからは「そんなのズルいっ!」って声が聞こえてきそうですが、私たちは使う側の立場なのでそんな事は気にせずに、「SQL Server を使用する時に快適ならいいじゃん!」って感覚でよいと思っておきましょう。
ただし、OleDbConnectionでSQL Server 7.0以降に接続できないというわけではありません。SQLOLEDBプロバイダの指定を行えば使用可能です。
(SqlConnection オブジェクトを使用する際は接続文字列やProviderプロパティによるOLEDBプロバイダの指定は不要です。)

それはさておき、今回は Jet OLEDB プロバイダを使用しますので、OleDbConnection を使用するということで、 次はADOの例のように OleDbConnection に Execute メソッドのような コマンドを実行するためのメソッドが存在するのかどうか、オブジェクトブラウザで調べてみることにします。

見た感じ、Execute メソッドまたはそれに変わるようなメソッドはなさそうです。
どうやらこのオブジェクトは完全に接続のみを管理するオブジェクトとなったようなので、ADO Command オブジェクトと同様なオブジェクトを使用する必要がありそうです。
さらに調査を続けてみると、System.Data.OleDb ネームスペース内にあるオブジェクトで OleDbCommand といういかにもあやしそうな名前をしたオブジェクトを発見しました。

もう一度MSDNで OleDbCommand オブジェクトについて調査したところ、コマンドを実行するために以下のようなメソッドがあることがわかりました。
メソッド 説明
ExecuteReader  行セットを返すコマンドの実行時に使用。
ExecuteNonQuery  INSERT, DELELE, UPDATE, SET ステートメントなど、結果セットを返さないコマンドの実行時に使用。
ExecuteScalar  SELECT COUNT(*) …など、データベースから単一の結果のみを取得する際に使用。
今回の仕様はSQLを実行した結果を順に出力していくというものですから、ExecuteReader を使用することになります。

ExecuteReaderの構文は以下のようになっています。

Public Function ExecuteReader() As System.Data.OleDb.OleDbDataReader

以前なら Command オブジェクトは Recordset を返していましたが、ADO.NET では OleDbDataReader というものを返すようです。
この OleDbDataReader、意味合いとしては ADO の Recordset と同じようなものらしいです。

これでコードを作成する上で必要な情報は大体集まりました。とにかく組み上げていきましょう。
私が作成したコードは以下のようなコードです。(System.Data.OleDbネームスペースをインポートしてあります)
 
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim oConn As OleDbConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Test.mdb")
    Dim oCmd As OleDbCommand
    Dim oReader As OleDbDataReader

    oConn.Open()
    oCmd = oConn.CreateCommand()
    oCmd.CommandText = "SELECT * FROM T_TEST"
    oReader = oCmd.ExecuteReader()
    
    While oReader.Read()
        Debug.WriteLine(CStr(oReader("ID")) & "," & CStr(oReader("NAME")))
    End While
    
    oReader.Close()
    oConn.Close()

End Sub
1行目のOleDbConnectionの宣言部は、 コンストラクタ(初期化コード)使用して接続文字列を渡しています。
2, 3行目はそれぞれ OleDbCommand オブジェクトと OleDbDataReader オブジェクトの宣言文です。
次に実行部ですが、OleDbConnection オブジェクト(接続)である oConn を Open し、OleDbCommand オブジェクトである oCmd を oConn の CreateCommand メソッドで初期化したのち、CommandText プロパティに実行するSQLステートメントを指定しています。
ここまでは、新しいオブジェクトを使用しているとはいえ、今までとはさほど変わったところはありません。
次に、oCmd の ExecuteReader メソッド(行セットを返すコマンドの実行)により OleDbDataReader オブジェクトである oReader で結果を取得し、行セットを順に読み込んでいくわけですが、
ここで新しい事がひとつあります。
今まで(ADO)は、次の行セットを読み込む場合、ADO.Recordsetオブジェクトの MoveNext メソッドを使用し、Eofプロパティが Trueになる(結果セットの終り)まで処理するというスタイルでした。
ADO.NETの OleDbDataReader オブジェクトで次のデータを読み込む場合は Read メソッドを使用し、この Reader メソッドは 次にデータ行が存在する場合、戻り値としてTrue を返し、そうではない場合は False を返します。
さらに、ADOではRecordsetオブジェクトを取得した時点でカーソルは先頭レコードに位置づけられていたのに対し、ADO.NET では OleDbDataReader オブジェクトの取得時は先頭レコードに位置づけられていません。
よって、上記のようにループの条件とメソッドの実行を一度に記述するような記述になったわけです。

ここで、「あれっ?」と思われた方もいらっしゃると思います。
ループ制御を行う While ステートメントの記述が、VB6までは While 〜 Wend から While 〜 End While に変わっています。
VB.NETでは言語の整合性を保つために、While ステートメントの終りは End While に変更されました。

話をADO.NETに戻します。
ループ中のデータをデバッグ出力するコードについて...、
VB6では Recordset の Fields コレクションにより各列の値を取得していましたが、VB.NET の OleDbDataReader オブジェクトはそれ自身が 列データのコレクションクラスとなっています。

VB6でも oRec("ID") というように VB.NET と同じような記述はできましたが、VB6の場合 Recordset オブジェクトのデフォルトのプロパティが Fields コレクションであるのに対し、VB.NETでは OleDvDataReader オブジェクト自身が列データのコレクションクラスであるという相違点があることを憶えておいてください。

さらに各フィールドの値を出力する際、すべて CStr にて型変換をしているところに注目してください。
OleDbDataReader オブジェクトの 各Item はObject型であるためにこのような記述をしています。
以前も少し触れましたが、VB6までは暗黙の型変換を行ってくれていたということを書きました。(このコードでは特に CStr を記述しなくても問題なく動作します。)
今までのVBプログラマはデータ型に対してそれほどシビアになる必要はありませんでしたが、これからは他言語との混在が可能になったことや安全なコードを書くといった意味でも、データ型に対してはシビアになるよう心掛けるべきです。
VB.NET本来の仕様もそのようにデザインされています。
VB.NET Beta 1では Strict オプションが On であったのに対し、Beta 2 ではこのオプションが Off になっただけです。
試しに、このフォームコードの冒頭に Option Strict On と記述し、CStr を削除し、
Debug.WriteLine(oReader("ID") & "," & oReader("NAME")) と記述を変更すると以下のようにコーディング時にエラーとして通知されます。


また話が横にそれてしましました。
最後に各オブジェクト(接続、データリーダ)を閉じるコードを記述します。ここは今までどおりですね。

以下がこのプロジェクトの実行結果です。

T_TESTの内容がきちんと出力されています。
 

ADO.NETを使用したデータベースへのアクセスに関して非常にシンプルな例をとりあげて説明してきました。
ADO.NETに関して、これはまだまだ序の口でさらに拡張された機能について次回以降、もっと詳しく調べていきたいと思います。


今日の収穫
1. ADO.NETの接続には SQL Server 7.0 以降用に最適化された SqlConnection オブジェクトか、 OleDbConnection オブジェクトを使用する。
2. 接続オブジェクトのExecuteメソッドは廃止された。
3. コマンドオブジェクトはSQLステートメントのタイプにより別々のメソッドが用意されている。
4. VB6の場合 Recordset オブジェクトのデフォルトのプロパティが Fields コレクションであるのに対し、VB.NETでは OleDbDataReader オブジェクト自身が列データのコレクションクラスである。
5. While〜Wend は While〜End While に変更された。
6. デバッグ出力は Debug.WriteLine と記述する。


 

Copyright©Sugi. All rights reserved.