ADO.NET相関図
|
.NETデータ・プロバイダを構成するクラス群
using System;
using System.Data.SqlClient;
class Reader
{
public static void Main()
{
string connStr = "Server=(local)\\SQLEXPRESS;" //接続文字列定義
+ "Trusted_Connection=yes;"
+ "database=pubs";
string sqlStr = "SELECT pub_id, pub_name FROM publishers"; //SQL文
SqlConnection conn = new SqlConnection(connStr); //DB接続先設定
SqlCommand cmd = new SqlCommand(sqlStr, conn); //SQL文を接続DBへ
conn.Open(); //DBへの接続開始
SqlDataReader dr = cmd.ExecuteReader(); //DBからの値の受け皿定義
while (dr.Read()) //DBから読み込み開始
//DBの中身を読み終わるとfalseになり、whileループから抜ける
{
Console.Write("{0},{1}\n", dr["pub_id"], dr["pub_name"]);
}
dr.Close(); //SqlDataReaderのリソース解放
conn.Close(); //SqlConnectionのリソース解放
}
}
- 接続文字列をセットしたSqlConnectionオブジェクトを作成
- select文をセットしたSqlCommandオブジェクトを作成
- ExecuteReaderメソッドによりselect文を実行し、SqlDataReaderオブジェクトを取得
- Readメソッドによりレコードを1行ずつ取得
|
SqlDataReader
SqlDataReaderオブジェクトに格納されているレコード(行データ)を、
SqlDataReaderクラスのReadメソッドにより、順に読み出していく。
ただし、Readメソッドは取得したレコードを返さず、
下の図のように内部で保持されている処理結果の現在のレコードを1つ進めるだけ。
- Readメソッドを何度か呼び出したあと、最後のレコードに達して、
現在のレコードをそれ以上進めることができない場合に
Readメソッドはfalseを返す(それまではtrueを返す)。
- また、最初の状態では現在のレコードは設定されておらず
(=最初のレコードの前にセットされており)、
最初にReadメソッドを呼び出した場合に、先頭のレコードが現在のレコードとなる。
- 現在のレコード上にある各カラム(各列)のデータは、
上図にあるようにSqlDataReaderクラスのインデクサにより取得する。
インデックス(添字)には、select文で指定したテーブルの列名を指定することができる。
- 読み出したデータ(各レコードにはpub_idとpub_nameの2つのデータが存在する)を画面に表示してみる。
この書き方はSqlDataReaderオブジェクトからデータを取得するときの定石だ。
while (dr.Read())
{
Console.Write("{0},{1}\n", dr["pub_id"], dr["pub_name"]);
}
dr.Close();
- HasRowsプロパティがあれば、処理結果中のレコードの有無による処理の場合分けを
シンプルに記述することができる。
このプロパティは、SqlDataReaderオブジェクトにレコードが格納されているかどうかを示す
⇒これまで、select文の結果の有無を調べるには、
実際にReadメソッドを呼び出してみるしかなかった。
|
記述方法のバリエーション
コンストラクタで必要なデータをすべて指定し、各オブジェクトを作成していた。
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(sqlStr, conn);
このコードは、コンストラクタを使わず、次のようにも書ける。
SqlConnection conn = new SqlConnection();
conn.ConnectionString = connStr;
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = sqlStr;
あるいは、SqlConnectionクラスにあるCreateCommandメソッドを利用して、次のように記述することもできる。
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText =sqlStr;
|
インターフェイス・ベースの記述
データ・プロバイダ固有クラスの使用を最小限に抑え、IDbConnectionインターフェイスにキャストすることで、
使用するデータベースを変えても、コードを大きく変更する必要がなくなる。
(IDbConnectionインターフェイスは、データ・プロバイダ固有クラスそれぞれに実装されている。)
using System;
using System.Data;
using System.Data.SqlClient;
class ReaderByInterface
{
public static void Main()
{
string connStr = "Server=(local)\\NetSDK;"
+ "Trusted_Connection=yes;"
+ "database=pubs";
string sqlStr = "SELECT pub_id, pub_name FROM publishers";
IDbConnection conn = new SqlConnection(connStr);
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = sqlStr;
conn.Open();
IDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Console.Write("{0},{1}\n", dr["pub_id"], dr["pub_name"]);
}
dr.Close();
conn.Close();
}
}
例えば、アクセス対象となるデータベース製品をSQL ServerからMicrosoft Accessに変更する場合でも、
SqlConnectionをOleDbConnectionと書き換えるだけでよい
|
insert文によるテーブルにレコードの挿入
「insert into テーブル名 (カラム名, ……) values (値, ……) 」
カラム部分で指定したカラム名の並びと、
値部分で指定した実際のデータの並びはそれぞれが対になっていなければならない。
どのタイミングで実行されるのだろう?
|
|
|
|
|
|
|
|