ADO.NET Managed Provider の使用法
ADO.NET では経験豊富な .NET データベース開発者向けに概要を説明する必要はありませんが、小型のユーティリティ・アプリケーションでたまに .NET を使用するだけであっても、この説明は役立つ可能性があります。このセクションでは、ADO.NET の概要として、簡単なデータベース・クエリを実行し、その結果を処理する方法を紹介します。
InterSystems ADO.NET Managed Provider を使用すると、Connection、Command、CommandBuilder、DataReader、DataAdapter などの汎用 ADO.NET Managed Provider クラスの完全互換バージョンで、.NET プロジェクトからインターシステムズ・データベースにアクセスできます。.NET アプリケーションを InterSystems IRIS に接続する方法の詳細は、"Connecting Your Application to InterSystems IRISOpens in a new tab" を参照してください。以下のクラスは、標準 ADO.NET Managed Provider クラスのインターシステムズ固有の実装です。
-
IRISConnection — 指定したインターシステムズ・ネームスペースのデータベースとアプリケーションとの間の接続を表します。IRISConnection の使用方法の詳細は、“インターシステムズ・データベースへの接続” を参照してください。
-
IRISCommand — IRISConnection で指定したネームスペース内のデータベースに対して実行する SQL 文またはストアド・プロシージャをカプセル化します。
-
IRISCommandBuilder — 単一テーブルのクエリをカプセル化するオブジェクトによって加えられた変更に合わせてデータベースを調整する SQL コマンドを自動で生成します。
-
IRISDataReader — IRISCommand で指定した結果セットをフェッチする方法を提供します。IRISDataReader オブジェクトは、結果セットに対する前方向のみの迅速なアクセスを提供します。ただし、ランダム・アクセスには対応していません。
-
IRISDataAdapter — IRISConnection で指定したネームスペース内のデータにマッピングされる結果セットをカプセル化します。これは、ADO.NET DataSet への入力やデータベースの更新に使用され、結果セットへの効率的なランダム・アクセス接続を実現します。
この章では、InterSystems ADO.NET Managed Provider クラスを使用したコードの具体例を示します。ここで説明する内容は以下のとおりです。
-
ADO.NET Managed Provider クラスの概要 — InterSystems ADO.NET Managed Provider クラスの使用法について簡単に説明します。
-
IRISCommand と IRISDataReader の使用法 — 読み取り専用の簡単なクエリの実行方法について説明します。
-
IRISParameter を使用した SQL クエリの使用法 — クエリにパラメータを渡す方法について説明します。
-
IRISDataAdapter と IRISCommandBuilder の使用法 — データの変更と更新を行います。
-
トランザクションの使用法 — トランザクションをコミットまたはロールバックする方法について説明します。
ADO.NET Managed Provider クラスの概要
ADO.NET Managed Provider クラスのインターシステムズ実装を使用するプロジェクトは非常にシンプルです。Sample.Person データベースを開いてその項目を読み取る、完成された実用的なコンソール・プログラムを以下に示します。
using System;
using InterSystems.Data.IRISClient;
namespace TinySpace {
class TinyProvider {
[STAThread]
static void Main(string[] args) {
string connectionString = "Server = localhost; Port = 51783; " +
"Namespace = USER; Password = SYS; User ID = _SYSTEM;";
using IRISConnection conn = new IRISConnection(connectionString);
conn.Open();
using IRISCommand command = conn.CreateCommand();
command.CommandText = "SELECT * FROM Sample.Person WHERE ID = 1";
IRISDataReader reader = command.ExecuteReader();
while (reader.Read()) {
Console.WriteLine($"TinyProvider output:\r\n " +
$"{reader[reader.GetOrdinal("ID")]}: {reader[reader.GetOrdinal("Name")]}");
}
reader.Close();
} // end Main()
} // end class TinyProvider
}
このプロジェクトには、以下の重要な機能があります。
-
using 文を使用すると、IRISClient アセンブリにアクセスできます。クライアント・コード用にネームスペースを宣言する必要があります。
using InterSystems.Data.IRISClient; namespace TinySpace {
-
IRISConnection conn オブジェクトは、USER ネームスペースへの接続を作成して開くのに使用します。conn オブジェクトは、常に適切に閉じられ、破棄されるように、using 宣言を使用して作成されます。
string connectionString = "Server = localhost; Port = 51783; " + "Namespace = USER; Password = SYS; User ID = _SYSTEM;"; using IRISConnection conn = new IRISConnection(connectionString); conn.Open();
-
IRISCommand command オブジェクトは、IRISConnection オブジェクトと SQL 文を使用して、ID が 1 の Sample.Person のインスタンスを開きます。
using IRISCommand command = conn.CreateCommand(); command.CommandText = "SELECT * FROM Sample.Person WHERE ID = 1";
-
IRISDataReader オブジェクトは、以下のように行のデータ項目へのアクセスに使用します。
IRISDataReader reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine($"TinyProvider output:\r\n " + $"{reader[reader.GetOrdinal("ID")]}: {reader[reader.GetOrdinal("Name")]}"); } reader.Close();
IRISCommand と IRISDataReader の使用法
読み取り専用の単純なクエリであれば、IRISCommand および IRISDataReader を使用して実行できます。すべてのデータベース・トランザクションと同様、このようなクエリの場合でも IRISConnection オブジェクトを開いておく必要があります。
この例では、既存の接続を使用する新しい IRISCommand オブジェクトに SQL クエリ文字列が渡されます。
string SQLtext = "SELECT * FROM Sample.Person WHERE ID < 10";
IRISCommand Command = new IRISCommand(SQLtext, Conn);
クエリの結果は、IRISDataReader オブジェクトに返されます。SQL 文で指定した列名を参照することで、プロパティにアクセスできます。
IRISDataReader reader = Command.ExecuteReader();
while (reader.Read()) {
Console.WriteLine(
reader[reader.GetOrdinal("ID")] + "\t"
+ reader[reader.GetOrdinal("Name")] + "\r\n\t"
+ reader[reader.GetOrdinal("Home_City")] + " "
+ reader[reader.GetOrdinal("Home_State")] + "\r\n");
};
列名ではなく列番号を使用した場合も、同じレポートを生成できます。IRISDataReader オブジェクトでは、前方への読み取りのみが可能です。データ・ストリームの先頭に戻るには、この読み取り操作をいったん終了し、クエリを再実行して読み取り操作をもう一度開始する必要があります。
reader.Close();
reader = Command.ExecuteReader();
while (reader.Read()) {
Console.WriteLine(
reader[0] + "\t"
+ reader[4] + "\r\n\t"
+ reader[7] + " "
+ reader[8] + "\n");
}
IRISParameter を使用した SQL クエリの使用法
IRISParameter オブジェクトは、より複雑な SQL クエリに必要です。以下の例では、IRISParameter で指定した文字列から始まる値を Name に持つすべての行からデータを選択しています。
string SQLtext =
"SELECT ID, Name, DOB, SSN "
+ "FROM Sample.Person "
+ "WHERE Name %STARTSWITH ?"
+ "ORDER BY Name";
IRISCommand Command = new IRISCommand(SQLtext, Conn);
このパラメータ値は、Name の先頭の文字列が A である行をすべて取得するように設定されています。このパラメータは IRISCommand オブジェクトに渡されます。
IRISParameter Name_param =
new IRISParameter("Name_col", IRISDbType.NVarChar);
Name_param.Value = "A";
Command.Parameters.Add(Name_param);
既定では、SQL 文はサーバ上で実行される前に検証されません。これは、クエリごとにサーバを 2 回呼び出す必要があるためです。検証が必要な場合は、IRISCommand.Prepare() を呼び出して、サーバに対する SQL 文の構文を検証します。
IRISDataReader オブジェクトでは、前述の例と同様に結果のデータ・ストリームにアクセスできます。
IRISDataReader reader = Command.ExecuteReader();
while (reader.Read()) {
Console.WriteLine(
reader[reader.GetOrdinal("ID")] + "\t"
+ reader[reader.GetOrdinal("Name")] + "\r\n\t"
+ reader[reader.GetOrdinal("DOB")] + " "
+ reader[reader.GetOrdinal("SSN")] + "\r\n");
};
IRISDataAdapter と IRISCommandBuilder の使用法
連続的な読み取り専用アクセス以外のアクセスをアプリケーションで行う必要がある場合は、IRISCommand および IRISDataReader クラスでは不十分です。このような場合は、IRISDataAdapter および IRISCommandBuilder クラスによって完全なランダム読み取り/書き込みアクセスを提供できます。以下に示す例では、これらのクラスを使用して、一連の Sample.Person 行を取得し、1 つの行を読み取って変更し、行を削除して新しい行を追加し、変更内容をデータベースに保存します。
IRISDataAdapter コンストラクタは、IRISCommand と同様に、SQL コマンドと IRISConnection オブジェクトをパラメータとして受け取ります。この例では、Name が A または B で始まるすべての Sample.Person 行のデータが結果セットに含まれます。Adapter オブジェクトは、この結果セットを Person という名前のテーブルにマッピングします。
string SQLtext =
" SELECT ID, Name, SSN "
+ " FROM Sample.Person "
+ " WHERE Name < 'C' "
+ " ORDER BY Name ";
IRISDataAdapter Adapter = new IRISDataAdapter(SQLtext, Conn);
Adapter.TableMappings.Add("Table", "Person");
Adapter オブジェクトに対して IRISCommandBuilder オブジェクトを作成します。Adapter オブジェクトによってマッピングされたデータが変更されると、Adapter は Builder によって生成された SQL 文を使用して、データベース内の対応する項目を更新します。
IRISCommandBuilder Builder = new IRISCommandBuilder(Adapter);
ADO の DataSet オブジェクトを作成し、Adapter を使ってデータを格納します。このオブジェクトには、PersonTable オブジェクトを定義するために使用されるテーブルが 1 つだけ含まれています。
System.Data.DataSet DataSet = new System.Data.DataSet();
Adapter.Fill(DataSet);
System.Data.DataTable PersonTable = DataSet.Tables["Person"];
簡単な foreach コマンドを使用して、PersonTable 内の各行を読み取ることができます。この例では、1 行目の Name を保存し、それを "Fudd, Elmer" に変更します。データを出力すると、すべての名前がアルファベット順に並んでいますが、1 行目だけは F で始まります。データを出力した後で、1 行目の Name を元の値にリセットします。どちらの変更も、DataSet 内のデータに対してのみ行われています。データベース内の元のデータはまだ変更されていません。
if (PersonTable.Rows.Count > 0) {
System.Data.DataRow FirstPerson = PersonTable.Rows[0];
string OldName = FirstPerson["Name"].ToString();
FirstPerson["Name"] = "Fudd, Elmer";
foreach (System.Data.DataRow PersonRow in PersonTable.Rows) {
Console.WriteLine("\t"
+ PersonRow["ID"] + ":\t"
+ PersonRow["Name"] + "\t"
+ PersonRow["SSN"]);
}
FirstPerson["Name"] = OldName;
}
次のコードでは、1 行目を削除するようマーク付けし、次に新しい行を作成して追加します。ここでも、これらの変更は DataSet オブジェクトに対してのみ行われています。
FirstPerson.Delete();
System.Data.DataRow NewPerson = PersonTable.NewRow();
NewPerson["Name"] = "Budd, Billy";
NewPerson["SSN"] = "555-65-4321";
PersonTable.Rows.Add(NewPerson);
最後に、Update() メソッドを呼び出します。Adapter は、今度は IRISCommandBuilder のコードを使用して、DataSet オブジェクトの Person テーブルに含まれる現在のデータでデータベースを更新します。
Adapter.Update(DataSet, "Person");
トランザクションの使用法
Transaction クラスは、SQL トランザクションの指定に使用します (トランザクションを使用する方法の概要は、"InterSystems SQL の使用法" の “トランザクション処理” を参照してください)。以下の例では、SSN が一意でない場合、トランザクション Trans が失敗して、ロールバックされます。
IRISTransaction Trans =
Conn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
try {
string SQLtext = "INSERT into Sample.Person(Name, SSN) Values(?,?)";
IRISCommand Command = new IRISCommand(SQLtext, Conn, Trans);
IRISParameter Name_param =
new IRISParameter("name", IRISDbType.NVarChar);
Name_param.Value = "Rowe, Richard";
Command.Parameters.Add(Name_param);
IRISParameter SSN_param =
new IRISParameter("ssn", IRISDbType.NVarChar);
SSN_param.Value = "234-56-3454";
Command.Parameters.Add(SSN_param);
int rows = Command.ExecuteNonQuery();
Trans.Commit();
Console.WriteLine("Added record for " + SSN_param.Value.ToString());
}
catch (Exception eInsert) {
Trans.Rollback();
WriteErrorMessage("TransFail", eInsert);
}