C#で学んだこと
DataBase

ADO.NET基礎講座
データベースの作成入門

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 (値, ……) 」 カラム部分で指定したカラム名の並びと、 値部分で指定した実際のデータの並びはそれぞれが対になっていなければならない。 どのタイミングで実行されるのだろう?