.NET 用 Caché オブジェクト・バインディングの使用法
Caché の最も重要な機能の 1 つに、データベースの各項目をリレーショナル・テーブルの行ではなくオブジェクトとして捉え、これらの項目にアクセスできる機能があります。Caché .NET バインディング・アプリケーションでは、Caché プロキシ・オブジェクトを使用してこの機能が実装されます。プロキシ・オブジェクトは、Caché クラス・ディクショナリに定義されたクラスから生成される .NET クラスのインスタンスです。各プロキシ・オブジェクトは、Caché サーバ上の対応するオブジェクトと通信するので、元のオブジェクトと同様に操作できます。生成されたプロキシ・クラスは、完全に互換性のある .NET マネージド・コードで記述されるので、プロジェクトのどの場所でも使用できます。
このセクションでは、Caché プロキシ・クラスを使用したコードの具体例を示します。
-
プロキシ・オブジェクトの概要 — プロキシ・オブジェクトの使用法を簡単に紹介します。
-
Caché プロキシ・クラスの生成 — さまざまなツールを使用してプロキシ・クラスを生成します。
-
Caché プロキシ・オブジェクトの使用法 — プロキシ・オブジェクトを使用して、Caché サーバ上にあるオブジェクトの作成、オープン、変更、保存、および削除を行います。
-
Caché クエリの使用法 — 既存の Caché クエリを使用して、結果セットの生成と操作を行います。
-
コレクションとリストの使用法 — Caché のリストと配列を操作します。
-
リレーションシップの使用法 — Caché リレーションシップ・オブジェクトを使用して、データ・セットへのアクセスとその操作を行います。
-
入出力リダイレクトの使用法 — Caché の Read 文と Write 文をリダイレクトします。
この章の例ではプロキシ・オブジェクトのみを使用して Caché データにアクセスしていますが、(“Caché ADO.NET Managed Provider クラスの使用法” で説明しているように) ADO.NET クラスや SQL 文を使用してデータベースのインスタンスにアクセスすることもできます。どちらのアクセス方法も同じプログラム内で使用できます。
この章に示す例は、bookdemos プロジェクト (詳細は、“Caché .NET サンプル・プログラム” を参照) で提供されているサンプルからの抜粋です。これらの例では、標準のコーディング作業に精通しているユーザを対象としているため、エラー・トラップ (try/catch) 文など、内容に直接関係のないコードは省略されています。完成された実用的なコード例の詳細は、<Cache-install-dir>\dev\dotnet\samples\bookdemos にある SampleCode.cs を参照してください (ご使用のシステムの <Cache-install-dir> の場所については、"Caché インストール・ガイド" の “Caché の既定のインストール・ディレクトリ” を参照してください)。
プロキシ・オブジェクトの概要
プロキシ・オブジェクトを使用する Caché .NET プロジェクトは非常にシンプルです。Sample.Person データベースを開いてその項目を読み取る、完成された実用的なコンソール・プログラムを以下に示します。
using System;
using InterSystems.Data.CacheClient;
using InterSystems.Data.CacheTypes;
namespace TinySpace {
class TinyProxy {
[STAThread]
static void Main(string[] args) {
CacheConnection CacheConnect = new CacheConnection();
CacheConnect.ConnectionString = "Server = localhost; "
+ "Port = 1972; " + "Namespace = SAMPLES; "
+ "Password = SYS; " + "User ID = _SYSTEM;";
CacheConnect.Open();
Sample.Person person = Sample.Person.OpenId(CacheConnect, "1");
Console.WriteLine("TinyProxy output: \r\n "
+ person.Id() + ": "
+ person.Name
);
person.Close();
CacheConnect.Close();
} // end Main()
} // end class TinyProxy
}
このプロジェクトは、“Caché ADO.NET Managed Provider クラスの使用法” に示した (プロキシ・オブジェクトを使用しない) プロジェクトとほぼ同じです。両方のプロジェクトには、以下の重要な機能があります。
-
同じ Using 文を追加できます。
using InterSystems.Data.CacheClient; using InterSystems.Data.CacheTypes;
-
同じコードを使用して、Caché の SAMPLES ネームスペースへの接続を生成し、開くことができます。
CacheConnection CacheConnect = new CacheConnection(); CacheConnect.ConnectionString = "Server = localhost; " + "Port = 1972; " + "Namespace = SAMPLES; " + "Password = SYS; " + "User ID = _SYSTEM;"; CacheConnect.Open();
-
どちらのプロジェクトにも、ID が 1 である Sample.PersonOpens in a new tab のインスタンスを開き、読み取るコードがあります。
ADO.NET プロジェクトとの間には、以下のように重要な相違点が 2 つあります。
-
この章のプロジェクトには、生成されたプロキシ・クラスのコードを含むファイル (WizardCode.cs) があります。このファイルを生成して目的のプロジェクトで扱えるようにする方法については、“Caché プロキシ・クラスの生成” を参照してください。
-
Sample.PersonOpens in a new tab のインスタンスにアクセスするには、CacheCommand オブジェクトや CacheDataReader オブジェクトではなく、プロキシ・オブジェクトを使用します。
SQL 文は必要ありません。代わりに、OpenId() クラス・メソッドの呼び出しによって、接続と必要なインスタンスが定義されます。
Sample.Person person = Sample.Person.OpenId(CacheConnect, "1");
インスタンスの各データ項目は、CacheReader でアクセスするデータ列ではなく、ドット表記で指定して直接アクセスできるメソッドやプロパティとして扱われます。
Console.WriteLine("TinyProxy output: \r\n " + person.Id() + ": " + person.Name );
多くの場合、プロキシ・オブジェクトを使用するコードは、ADO.NET Managed Provider クラスを使用するコードよりもはるかに記述や維持が簡単です。プロジェクトでは、両方のアクセス方法を切り換えて使用できます。これは、指定された状況に対してどちらの方法が最適であるかによって決まります。
Caché プロキシ・クラスの生成
このセクションでは、以下のトピックについて説明します。
-
Caché オブジェクト・バインディング・ウィザードの使用法 — プロキシ・クラスの生成プロセスを説明する GUI プログラムについて紹介します。
-
コマンド行からのプロキシ・ジェネレータの実行 — バッチ・ファイルまたは ANT スクリプトからプロキシ・クラスを生成するための DOS プログラムについて説明します。
-
プログラムによるプロキシ・ファイルの生成 — プロキシ・ジェネレータのメソッドを直接呼び出して .NET プログラム内からプロキシ・クラスを生成します。
-
プロジェクトへのプロキシ・コードの追加 — 新しいプロキシ・ファイルを生成した後の操作について説明します。
-
Caché システム・クラスから継承されるメソッド — プロキシ・ジェネレータがすべてのプロキシ・ファイルに追加する一連の標準メソッドについて説明します。
Caché オブジェクト・バインディング・ウィザードの使用法
Caché オブジェクト・バインディング・ウィザードは、スタンドアロン・プログラム (既定で <Cache-install-dir>\dev\dotnet\bin\v2.0.50727 に格納されている CacheNetWizard.exe) として実行することも、Visual Studio に組み込まれたツール (“Visual Studio への Caché オブジェクト・バインディング・ウィザードの追加” を参照) として使用することもできます。
ウィザードを起動すると、以下のウィンドウが表示されます。
以下の情報を入力します。
-
接続する Caché サーバを選択します。
.NET クラスの生成対象とする Caché クラスを含むサーバを選択します。サーバを選択するには、以下の手順を実行します。
-
[接続]をクリックして、使用するサーバを選択します。
-
指示に従ってユーザ名とパスワードを入力します。Cache 接続マネージャが表示されます。
-
使用するクラスを含むネームスペース (この場合は、bookdemos プロジェクトの SAMPLES) を選択します。
-
[OK] をクリックします。
-
-
言語の選択 :
bookdemos プロジェクトの場合、[言語 : C#] を選択します。
-
ウィザードの出力先を選択します。
通常、使用するプロジェクトの .csproj ファイルが格納されているフォルダが出力先になります。この例では、出力ファイルの名前は WizardCode.cs となり、bookdemos プロジェクトのメイン・ディレクトリに格納されます。
-
使用するクラスを選択します。
この演習では、SAMPLES ネームスペースから Sample.Person クラスと Sample.Company クラスを選択します。Sample.Address クラスとSample.Employee クラスは、Sample.Person と Sample.Company で使用されるため、自動的に追加されます。[システム・クラスを表示] にチェックを付けると、SAMPLES のクラスと共に %SYS (標準の Caché クラス・ライブラリ) のクラスが表示されます。
-
ジェネレータのオプションは以下のとおりです。
この演習では、[既定の引数を指定したメソッド] にチェックを付けて、その他のフィールドは空のままにしておきます。オプションは以下のとおりです。
-
.Net Compact Framework を使用 — モバイル・アプリケーション用のプロキシ・コードを生成します。
-
既定の引数を指定したメソッド — 特定のシステム・メソッドに対して多少のオーバーロードをオプションで生成します。
-
アプリケーション・ネームスペース — 生成されたすべてのプロキシ・クラスの名前に追加されるオプションのネームスペースです。例えば、ユーザが「MyNamespace」と入力した場合、生成されたコードには、単に Sample.Person ではなく MyNamespace.Sample.Person への参照が含まれます。
Note:サーバはこのネームスペースには関知しません。関係で参照されるプロキシ・オブジェクトが確実に正しく生成されるように、アプリケーションのメイン・アセンブリの名前を使用するか、または CacheConnection.AppNamespace をここで入力した値に設定する必要があります (詳細は、“Caché プロキシ・オブジェクトの使用法” の “プロキシ・オブジェクトの名前でのインスタンス化” を参照してください)。
-
-
[生成] を押してクラスを作成します。
これで、生成したファイルがプロジェクトに追加されます (“プロジェクトへのプロキシ・コードの追加” を参照してください)。
コマンド行からのプロキシ・ジェネレータの実行
コマンド行プロキシ・ジェネレータ・プログラム (既定で <Cache-install-dir>\dev\dotnet\bin\v2.0.50727 に格納されている dotnet_generator.exe)
は、同じプロキシ・ファイルのセットを頻繁に再生成する必要がある場合に便利です。Caché クラスの開発中は、Caché クラスのインタフェースを変更するたびにプロキシ・クラスを再生成する必要があるため、この機能が重要になります。
コマンド行ジェネレータには常に、接続文字列、出力パスと出力ファイルのタイプ (cs または vb)、および生成されるクラスのリストに関する情報が必要です。使用される引数は以下のとおりです。
-
-conn <connection string> — 標準の接続文字列です (“接続の作成” を参照してください)。
-
すべてのクラスに対して単一の出力ファイルを生成する場合は、-path を使用します。
-
-path <full filename> — 生成されたコードの出力ファイルのパスと名前です。生成される出力ファイルのタイプはファイル名の拡張子によって決まります (例えば、C:\somepath\WizardCode.vb では Visual Basic のコード・ファイルが生成されます)。
-
-
クラスごとに 1 つの出力ファイルを生成する場合は、-dir および -src-kind を使用します。
-
-dir <path> — 生成されたプロキシ・ファイルが配置されるディレクトリです。
-
-src-kind <cs|vb> — 生成するプロキシ・ファイルのタイプです。クラスごとに、-dir に指定したディレクトリに <namespace_classname>.<src-kind> という名前のファイルが生成されます。指定可能なオプションは、cs または vb です。
-
-
-class-list <full filename> — 使用するクラスのリストが含まれるテキスト・ファイルのパスと名前です。各クラス名は別々の行に指定する必要があります。
また、以下のオプション引数も使用できます。
-
-gen-default-args <true | false> — 生成された特定のシステム・メソッドに対してオプションのオーバーロードを生成するかどうかを制御するスイッチです。指定可能なオプションは、true または false です。
-
-app-nsp<namespace> — 生成されたすべてのプロキシ・クラスの名前に追加されるオプションのネームスペースです。例えば、ユーザが「MyNamespace」と入力した場合、生成されたコードには、単に Sample.Person ではなく MyNamespace.Sample.Person への参照が含まれます。
-
-use-cf <true | false> — モバイル・デバイスまたは標準の PC 用にコードを生成するかどうかを制御するスイッチです。指定可能なオプションは、true または false です。指定可能なオプションは、true または false です。
この例の DOS バッチ・ファイルは dotnet_generator を 2 回呼び出して、以下の出力を生成します。
-
最初の呼び出しでは、いくつかのプロキシ・クラスを含む単一のファイルが生成されます。このコマンドにより、オブジェクト・バインディング・ウィザード (“Caché オブジェクト・バインディング・ウィザードの使用法” の例を参照) とまったく同じ WizardCode.cs ファイルが生成されます。
-
2 番目の呼び出しでは、各クラスに対して 1 つのプロキシ・ファイルが生成され、C# ではなく Visual Basic コードが生成されます。ファイル名は <namespace_classname>.vb のような形式になります。
両方の呼び出しで、同じ接続文字列、出力ディレクトリ、およびクラス・リスト・ファイルを使用します。
set netgen=C:\Intersystems\Cache\dev\dotnet\bin\v2.0.50727\dotnet_generator.exe
set clist=C:\Intersystems\Cache\dev\dotnet\samples\bookdemos\Classlist.txt
set out=C:\Intersystems\Cache\dev\dotnet\samples\bookdemos
set conn="Server=localhost;Port=1972;Namespace=SAMPLES;Password=SYS;User ID=_SYSTEM;"
rem CALL #1: Generate a single WizardCode.cs proxy file
%netgen% -conn %conn% -class-list %clist% -path %out%\WizardCode.cs -gen-default-args true
rem CALL #2: Generate one <namespace_classname>.vb proxy file for each class
%netgen% -conn %conn% -class-list %clist% -dir %out% -src-kind vb -gen-default-args true
クラス・リスト・ファイル Classlist.txt の内容は以下のとおりです。
Sample.Company
Sample.Person
リストされているのは 2 つのクラスのみですが、Sample.AddressOpens in a new tab および Sample.EmployeeOpens in a new tab のプロキシ・クラスは Sample.PersonOpens in a new tab および Sample.CompanyOpens in a new tab で使用されるため自動的に生成されます。
プログラムによるプロキシ・ファイルの生成
CacheConnection クラスには、.NET プログラム内からのプロキシ・ファイルを生成するために使用できる、以下のメソッドが含まれています。
新しい CS または VB プロキシ・ファイルを生成します。このファイルには、いくつかのクラス定義が含まれる場合があります。
CacheConnection.GenSourceFile(filepath, generator, classlist, options, errors);
パラメータ :
-
filepath — 生成されるファイルのパスおよびファイル名を含む文字列。
-
generator — CS または VB コードのいずれかを生成する CodeDomProvider オブジェクト。
-
classlist — 生成されるクラスのリストをポイントする IEnumerator 反復子。
-
options — CacheClient.ObjBind.GeneratorOptions オブジェクト。
-
errors — 返されるすべてのエラー・メッセージを格納する IList 配列。
classlist 内の各クラスに対して <classname>.<filetype> という名前の個別の CS または VB プロキシ・ファイルを生成します。
CacheConnection.GenMultipleSourceFiles(dirpath, filetype, generator, classlist, options, errors);
パラメータ :
-
dirpath — 生成されるファイルのディレクトリ・パスを含む文字列。
-
filetype — 生成されるコードに基づいて ".vb" または ".cs" のいずれかを含む文字列。
-
generator — CS または VB コードのいずれかを生成する CodeDomProvider オブジェクト。
-
classlist — 生成されるクラスのリストをポイントする IEnumerator 反復子。
-
options — CacheClient.ObjBind.GeneratorOptions オブジェクト。
-
errors — 返されるすべてのエラー・メッセージを格納する IList 配列。
両方のメソッドを使用している実用的な例は、bookdemos サンプル・プログラムの Proxy_8_MakeProxyFiles() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
プロキシ・ジェネレータ・メソッドの使用法
以下のコード例は、メソッドのパラメータを定義して、各プロキシ・ジェネレータ・メソッドを呼び出す方法を示しています。
generator は、CSharpCodeProvider または VBCodeProvider のいずれかになります。
System.CodeDom.Compiler.CodeDomProvider CS_generator = new CSharpCodeProvider();
System.CodeDom.Compiler.CodeDomProvider VB_generator = new VBCodeProvider();
各メソッドは、生成されるクラスのリストをポイントする反復子を引数に取ります。以下の例にリストされているのは 2 つのクラスのみですが、Sample.AddressOpens in a new tab および Sample.EmployeeOpens in a new tab のプロキシ・クラスは Sample.PersonOpens in a new tab および Sample.CompanyOpens in a new tab で使用されるため自動的に生成されます。
ArrayList classes = new ArrayList();
classes.Add("Sample.Company");
classes.Add("Sample.Person");
System.Collections.IEnumerator classlist
classlist = classes.GetEnumerator();
この例では、プロキシ・コードに対して特別なネームスペースは生成されず、継承されたメソッドの完全なセットが各クラスに対して生成されます。また、モバイル・アプリケーションで使用するための追加のコードも生成されません。
InterSystems.Data.CacheClient.ObjBind.GeneratorOptions options
options = new GeneratorOptions();
options.AppNamespace = "";
options.GenDefaultArgMethods = true;
options.UseCF = false;
errors パラメータには、プロキシ・ジェネレータ・メソッドの呼び出しから返されるエラー・メッセージ (ある場合) が格納されます。3 つのすべてのメソッドでこのパラメータが使用されます。
System.Collections.IList errors
errors = new System.Collections.ArrayList();
この例は、WizardCode.cs という名前の C# プロキシ・ファイルをディレクトリ C:\MyApp\ に生成します。このファイルには、Sample.PersonOpens in a new tab、Sample.CompanyOpens in a new tab、Sample.AddressOpens in a new tab、および Sample.EmployeeOpens in a new tab 用のコードが含まれます。
string filepath = @"C:\MyApp\WizardCode.cs";
System.CodeDom.Compiler.CodeDomProvider generator = new CSharpCodeProvider();
conn.GenSourceFile(filepath, generator, classlist, options, errors);
この例は、クラスごとに単一の VB プロキシ・ファイルを生成します。
string dirpath = @"C:\MyApp\";
string filetype = ".vb";
System.CodeDom.Compiler.CodeDomProvider generator = new VBCodeProvider();
conn.GenMultipleSourceFiles(dirpath, filetype, generator, classlist, options, errors);
以下のファイルが C:\MyApp\ に生成されます。
Person.vb
Company.vb
Address.vb
Employee.vb
Sample.AddressOpens in a new tab および Sample.EmployeeOpens in a new tab のプロキシ・ファイルは Sample.PersonOpens in a new tab および Sample.CompanyOpens in a new tab で使用されるため自動的に生成されます。
プロジェクトへのプロキシ・コードの追加
.NET プロキシ・ファイルを生成した後、使用するプロジェクトにプロキシ・コードを以下の手順で追加します。
-
Visual Studio のメイン・メニューで、[プロジェクト]→[既存項目の追加] を選択します。
-
生成されたプロキシ・ファイル (クラスごとに 1 つのファイルを生成するよう選択した場合は複数のファイル) を参照して、[追加] をクリックします。
Visual Studio のソリューション・エクスプローラにこのファイルが表示されます。
以下に示すように、これでプロキシ・オブジェクトを使用できます。
生成されたプロキシ・クラスは、対応する Caché クラスを変更しても自動的には更新されません。生成されたクラスは、プロキシ・クラスが生成されたときに存在したプロパティ、メソッド、およびクエリのシグニチャに変更がない限り、引き続き機能します。シグニチャが変更されていると、プロキシ・クラスは何が変更または削除されたのかについての記述と共に CacheInvalidProxyException をスローします。
Caché システム・クラスから継承されるメソッド
プロキシ・ファイル・ジェネレータでは、標準の Caché クラス・ライブラリから継承された特定のクラスに対するプロキシ・メソッドも提供されます。例えば、Sample クラスは、Caché の %Library.PersistentOpens in a new tab および %Library.PopulateOpens in a new tab からメソッドを継承します。これらのメソッドに対するプロキシは、プロキシ・ファイルを生成する際に自動的に追加されます。このセクションでは、使用頻度の高いメソッドの概要を説明します。各メソッドの詳細は、"Caché クラス・リファレンス" にあるこれらのクラスの情報を参照してください。Caché オブジェクトの使用に関する一般的なガイドの詳細は、“Caché オブジェクトの使用法” の “登録オブジェクトを使用した作業” を参照してください。
以下の %Library.PersistentOpens in a new tab プロキシが生成されます。
-
Id() — このオブジェクトの永続オブジェクト ID がある場合は、その ID を返します。 オブジェクト ID がない場合は、NULL 文字列を返します。
string ID = person.Id();
-
Save() — ディスクにメモリ内のオブジェクトを保存します。そのオブジェクトが既にディスクに保存されている場合 (したがって、OID も存在する場合)、Save() はディスクのオブジェクトを更新します。そのオブジェクトがまだディスクに保存されていない場合、Save() はオブジェクトを保存して、新しい OID を生成します。
CacheStatus sc = person.Save();
-
Open() — データベースのオブジェクトをメモリ上にロードし、そのオブジェクトを参照する OREF を返します。
-
OpenId() — データベースのオブジェクトをメモリ上にロードし、そのオブジェクトを参照する OREF を返します。OpenId() の機能は、インスタンスの取得に OID 値ではなく ID 値を使用する点を除いて、Open() メソッドの機能と同じです。
Sample.Person person = Sample.Person.OpenId(CacheConnect, "1");
-
ExistsId() — 指定した ID で識別されるオブジェクトがエクステント内に存在するかどうかを確認します。
if (!(bool)Sample.Person.ExistsId(CacheConnect, ID)) { string Message = "No person with id " + ID + " in database."; };
-
DeleteId() — 指定した ID で保存されているオブジェクトをデータベースから削除します。
CacheStatus sc = Sample.Person.DeleteId(CacheConnect, ID);
-
Extent() — システム提供のクエリ。このエクステントにあるすべてのインスタンスを含む結果セットを生成します。
CacheCommand Command = Sample.Person.Extent(CacheConnect);
-
KillExtent() — クラスとそのサブクラスのインスタンスをすべて削除します。
CacheStatus sc = Sample.Person.KillExtent(CacheConnect)
以下の %Library.PopulateOpens in a new tab プロキシが生成されます。
-
Populate() — 1 つのクラスに属する、指定した数のインスタンスを作成し、データベースに保存します。
long newrecs = (long)Sample.Person.Populate(CacheConnect, 100);
-
OnPopulate() — 生成されたデータを詳細に制御するには、クラス内で OnPopulate() メソッドを定義します。OnPopulate() メソッドが定義されると、Populate() メソッドは、オブジェクトを生成するたびにこのメソッドを呼び出します。
-
PopulateSerial() — シリアル・オブジェクトの単独のインスタンスを作成します。
KillExtent() メソッドおよび Populate() メソッドを使用している実用的な例は、bookdemos サンプル・プログラムの Proxy_6_Repopulate() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
プロキシ・オブジェクトの使用法
Caché プロキシ・オブジェクトは、データベースのインスタンスに対して標準のほとんどの操作を実行する際に使用できます。このセクションでは、インスタンスを開いて読み取る方法、インスタンスを作成または削除する方法、および既存のインスタンスを変更して保存する方法について説明します。
オブジェクトのオープンと読み取り
OpenId() メソッドを使用し、ID を指定してインスタンスにアクセスします (“Caché クエリの使用法” で後述するように、SQL クエリを使用してインスタンスにアクセスすることもできます)。OpenId() はスタティック・クラス・メソッドであり、以下のようにインスタンス名ではなくタイプ名で指定します。
Sample.Person person = Sample.Person.OpenId(CacheConnect, "1");
オブジェクトをインスタンス化しておくと、標準ドット表記を使用して person 情報の読み取りや書き込みが可能になります。
string Name = person.Name
string ID = person.Id();
person.Home.City = "Smallville";
person.Home.State = "MN";
この例では、person.Home は、実際には Sample.AddressOpens in a new tab の埋め込みオブジェクトです。Sample.PersonOpens in a new tab オブジェクトと連動して、自動的に作成または破棄されます。
実用的な例は、bookdemos サンプル・プログラムの Proxy_1_ReadObject() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
オブジェクトの作成と保存
Caché プロキシ・オブジェクトのコンストラクタは、CacheConnection オブジェクトの情報を使用して、プロキシ・オブジェクトと Caché サーバ上の対応するオブジェクトとのリンクを作成します。
Sample.Person person = new Sample.Person(CacheConnect);
person.Name = "Luthor, Lexus A.";
person.SSN = "999-45-6789";
Save() メソッドを使用して、データベースに永続インスタンスを作成します。このインスタンスを保存しておくと、Id() メソッドを使用して、新たに生成された ID 番号を取得できます。
CacheStatus sc = person.Save();
Display.WriteLine("Save status: " + sc.IsOK.ToString());
string ID = person.Id();
Display.WriteLine("Saved id: " + person.Id());
ExistsId() クラス・メソッドは、データベースにインスタンスが存在するかどうかを確認する際に使用できます。
string personExists = Sample.Person.ExistsId(CacheConnect, ID).ToString()
Display.WriteLine("person " + ID + " exists: " + personExists)
実用的な例は、bookdemos サンプル・プログラムの Proxy_2_SaveDelete() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
プロキシ・オブジェクトの名前でのインスタンス化
サーバから返されるオブジェクトが、クライアントが要求したオブジェクトと異なる場合があります。例えば、クライアントが Sample.PersonOpens in a new tab のインスタンスを要求したが、サーバが Sample.EmployeeOpens in a new tab を返す場合です。必要なクラスのオブジェクトをインスタンス化するために、バインディングは、アプリケーションのネームスペース (ある場合) を含むプロキシ・タイプの正確な名前を認識している必要があります。
プロキシ・クラスが生成されるとき、このプロキシ・クラスを含むネームスペースを指定するオプションがあります。例えば、アプリケーションのネームスペースが MyAppNsp の場合、Sample.PersonOpens in a new tab プロキシ・クラスを MyAppNsp.Sample.Person に指定できます。または、このオブジェクトを Sample.PersonOpens in a new tab として生成し、"MyAppNsp" を connection.AppNamespace プロパティに割り当てることができます。いずれのオプションでも、バインディングは、プロキシ・タイプの完全名が "MyAppNsp.Sample.Person" であることを推測できます。
バインディングでは、名前でのインスタンス化をできる限り回避しようとするため、クラスが既にメモリにロードされている場合、バインディングはメモリ内のタイプを使用してインスタンスを作成します。この場合、正確なクラス名は必要ありません。以下の例では、Y() は、Sample.PersonOpens in a new tab である必要があることをクライアントが認識しているプロキシ・オブジェクトを返します。
Sample.Person p = new Sample.Person(conn);
Sample.Person q = x.Y();
最初の行でオブジェクト p が作成され、メモリに Sample.PersonOpens in a new tab がロードされます。この場合、バインディングは完全名を必要とせず、x.Y() は例外をスローしません。最初の行をコメントにすると、プロキシ・クラスの完全名が実際に "MyAppNsp.Sample.Person" のような名前の場合、2 行目でエラーが発生します。
プロキシ・オブジェクトのクローズ
Close() メソッドはプロキシ・オブジェクトを切断し、サーバ上の対応するオブジェクトを閉じますが、データベースにある永続インスタンスは変更しません。
person.Close();
プロキシ・オブジェクトを破棄する場合は、常に Close() を使用します。
クライアントではオブジェクト参照カウントが保持されません。(参照によって、または返り値として) サーバからオブジェクトを返すたびに、サーバの参照カウントが増加します。Close() が呼び出されると参照カウントは減少します。このカウントが 0 になると、サーバのオブジェクトが閉じます。
以下のようなコードは使用しないでください。
person = nothing; //Do NOT do this!
このコードを実行すると、クライアント側のプロキシ・オブジェクトは閉じますが、サーバの参照カウントが減少しません。これにより、コード上はオブジェクトが閉じられたと見なされる一方で、サーバ上のオブジェクトが開いたままになる可能性があります。
既定では、Close() 呼び出しはキャッシュされます。プロキシ・オブジェクトは使用できなくなりますが、実際にはサーバ上で参照カウントがデクリメント可能になるまで破棄されません。これはサーバの再呼び出しまでは発生しません (例えば、別のプロキシ・オブジェクトでのメソッド呼び出し時など)。
状況によっては、キャッシュを行うことは望ましくない場合があります。例えば、オブジェクトが並行処理レベル 4 (排他ロック) で開いている場合、ロックは次のサーバ呼び出しまで解除しません。直ちにオブジェクトを破棄するには、オプションの useCache パラメータを False に設定して Close() を呼び出すことができます。
person.Close(false);
これにより、メッセージが即座にサーバに送信され、プロキシ・オブジェクトの破棄およびリソースの解放を行います。
データベースからの永続オブジェクトの削除
DeleteId() クラス・メソッドは、データベースからインスタンスを削除します。以下のように ExistsId() メソッドを使用すると、インスタンスが削除されたことを確認できます。
CacheStatus sc = Sample.Person.DeleteId(CacheConnect, ID);
Display.WriteLine("Delete status: " + sc.IsOK.ToString());
Display.WriteLine("person " + ID + " exists: "
+ Sample.Person.ExistsId(CacheConnect, ID).ToString());
実用的な例は、bookdemos サンプル・プログラムの Proxy_2_SaveDelete() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
Caché クエリの使用法
Caché クエリは、Caché クラスの一部として定義される SQL クエリです。例えば、Sample.PersonOpens in a new tab クラスで ByName クエリを以下のように定義しているとします。
Query ByName(name As %String = "") As %SQLQuery(CONTAINID = 1, SELECTMODE = "RUNTIME")
[ SqlName = SP_Sample_By_Name, SqlProc ]
{
SELECT ID, Name, DOB, SSN
FROM Sample.Person
WHERE (Name %STARTSWITH :name)
ORDER BY Name
}
クエリからリレーショナル・テーブルが返されるため、Caché プロキシ・オブジェクトは特定の ADO.NET クラスを利用してクエリ結果を生成します。Sample.PersonOpens in a new tab プロキシ・クラスでは、ByName はクラス・メソッドです。接続オブジェクトを引数に取り、事前定義された以下の SQL クエリの実行に使用できる ADO.NET Managed Provider の CacheCommand オブジェクトを返します。
CacheCommand Command = Sample.Person.ByName(CacheConnect);
この例では、Command.Connection プロパティが CacheConnect に設定され、Command.CommandText に事前定義された ByName クエリ文字列が含まれています。
Command.Parameters プロパティを設定するには、A という値を持つ CacheParameter オブジェクトを作成して追加します (これにより、A で始まる値を Name フィールドに持つすべてのレコードが取得されます)。
CacheParameter Name_param = new CacheParameter("name", CacheDbType.NVarChar);
Name_param.Value = "A";
Command.Parameters.Add(Name_param);
CacheParameter および CacheDataReader ADO.NET Managed Provider クラスは、ADO.NET の SQL クエリと同様に、パラメータを定義してクエリを実行するために使用する必要があります (“CacheParameter を使用した SQL クエリの使用法” を参照してください)。ただしこの例では、クエリを使用して、オブジェクトへのアクセスに使用される一連のオブジェクト ID を返しています。
CacheDataReader オブジェクトを使用して、結果セットにある各行の ID が取得されます。各 ID は、対応する Sample.PersonOpens in a new tab プロキシ・オブジェクトのインスタンス化に使用されます。この後、このオブジェクトはデータへのアクセスに使用されます。
Sample.Person person;
string ID;
CacheDataReader reader = Command.ExecuteReader();
while (reader.Read()) {
ID = reader[reader.GetOrdinal("ID")].ToString();
person = Sample.Person.OpenId(CacheConnect, ID);
Display.WriteLine(
person.Id() + "\t"
+ person.Name + "\n\t"
+ person.SSN + "\t"
+ person.DOB.ToString().Split(' ')[0].ToString()
);
};
実用的な例は、bookdemos サンプル・プログラムの Proxy_3_ByNameQuery() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
コレクションとリストの使用法
Caché プロキシ・オブジェクトは、Caché コレクションとストリームを標準 .NET オブジェクトとして解釈します。コレクションは、foreach などの反復子で操作可能で、add() や insert() などの標準メソッドを実装できます。Caché リスト ($List 形式) は、CacheSysList オブジェクトとして解釈され、CacheSysListReader のインスタンスによってアクセスされます (InterSystems.Data.CacheTypes ネームスペースにあります)。
シリアル・オブジェクトのコレクションは .NET Dictionary オブジェクトとして公開されます。シリアル・オブジェクトはグローバル・ノードとして保持され、ここに各ノード・アドレスおよび値が Dictionary キーおよび値として格納されます。
Person クラスには、文字列の Caché リストである FavoriteColors プロパティがあります。foreach 反復子を使用すると、このリストの要素にアクセスできます。
CacheListOfStrings colors = person.FavoriteColors
int row = 0;
foreach (string color in colors) {
Display.WriteLine(" Element #" + row++ + " = " + color);
}
標準コレクション・メソッドを使用できます。以下の例では、最初の要素を削除し、別の値を新しい最初の要素として挿入します。さらに、最後の要素を追加します。
if (colors.Count > 0) colors.RemoveAt(0);
colors.Insert(0,"Blue");
colors.Add("Green");
実用的な例は、bookdemos サンプル・プログラムの Proxy_4_Collection() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
Caché はコレクションから継承されるプロキシ・クラスの生成をサポートしません。例えば、Caché プロキシ・ジェネレータは以下の ObjectScript クラスのプロキシを生成しようとするとエラーをスローします。
Class User.ListOfPerson Extends %Library.ListOfObjects
{Parameter ELEMENTTYPE = "Sample.Person";}
リレーションシップの使用法
Caché データベースでリレーションシップが定義されている場合、Caché プロキシ・ジェネレータは、このリレーションシップをカプセル化する CacheRelationshipObject クラスを生成します。Sample.CompanyOpens in a new tab クラスには、Sample.EmployeeOpens in a new tab (Sample.PersonOpens in a new tab のサブクラス) との一対多のリレーションシップがあります。以下の例では、Sample.EmployeeOpens in a new tab のインスタンスを開いた後、このリレーションシップを使用して、従業員のリストを生成しています。
標準の OpenId() メソッドで employee インスタンスを開きます。このインスタンスには、対応する company オブジェクトのインスタンス化に使用する Company リレーションシップがあります。
Sample.Employee employee = Sample.Employee.OpenId(CacheConnect,ID)
Sample.Company company = employee.Company;
Display.WriteLine("ID: " + (string)employee.Id());
Display.WriteLine("Name: " + employee.Name)
Display.WriteLine("Works at: " + company.Name);
company オブジェクトには、逆の関係となる Employees リレーションシップがあります。この例では、colleagues という名前のオブジェクトとしてインスタンス化されています。これにより、colleagues オブジェクトは、Employee オブジェクト・セットを含むコレクションとして処理できます。
CacheRelationshipObject colleagues = company.Employees;
Display.WriteLine("Colleagues: ");
foreach (Sample.Employee colleague in colleagues) {
Display.WriteLine("\t" + colleague.Name);
}
実用的な例は、bookdemos サンプル・プログラムの Proxy_5_Relationship() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。
入出力リダイレクトの使用法
Caché のメソッドで Read 文または Write 文が呼び出されると、これらの文は既定でクライアント・マシンの標準入力または標準出力に関連付けられます。例えば、Sample.EmployeeOpens in a new tab クラスの PrintPerson() メソッドには以下の行が含まれます。
Write !,"Name: ", ..Name, ?30, "Title: ", ..Title
以下の例は、Sample.EmployeeOpens in a new tab プロキシ・オブジェクトから PrintPerson() を呼び出します。
Sample.Employee employee = Sample.Employee.OpenId(CacheConnect, "102");
employee.PrintPerson();
既定では、この呼び出しの出力は、CacheConnection.DefaultOutputRedirection 委任オブジェクトを使用してクライアント・コンソールにリダイレクトされ、次のコードに実装されます。
public static OutputRedirection DefaultOutputRedirection =
new OutputRedirection(CacheConnection.OutputToConsole);
static void OutputToConsole(string output)
{
Console.Out.Write(output);
}
既定のリダイレクトの委任は、CacheConnection オブジェクトの作成時に定義されます。コンストラクタでは、次の例のようなコードが実行されます。
private void Init() {
OutputRedirectionDelegate = DefaultOutputRedirection;
InputRedirectionDelegate = DefaultInputRedirection;
}
独自の出力リダイレクトを指定するには、OutputToConsole と同じシグニチャを使用して出力メソッドを実装し、委任先に新しいメソッドを指定した OutputRedirection オブジェクトを作成して、この新しいオブジェクトを接続オブジェクトの OutputRedirectionDelegate フィールドに割り当てる必要があります。
この例は、出力を System.IO.StringWriter ストリームにリダイレクトします。最初に、新しい出力リダイレクト・メソッドを定義します。
static System.IO.StringWriter WriteOutput;
static void RedirectToStream(string output)
{
MyClass.WriteOutput.Write(output);
}
この新しいメソッドによって出力が WriteOutput ストリームにリダイレクトされ、後で StringReader によってアクセスできるようになります。新しい委任を使用するには、WriteOutput ストリームをインスタンス化し、新しい接続 conn を開いて、RedirectToStream() を conn で使用する委任として設定します。
WriteOutput = new System.IO.StringWriter();
conn = new CacheConnection(MyConnectString);
conn.Open();
conn.OutputRedirectionDelegate =
new CacheConnection.OutputRedirection(MyClass.RedirectToStream);
PrintPerson() が呼び出されると、結果の出力が WriteOutput にリダイレクトされます (これにより、出力が基礎となる StringBuilder に格納されます)。これで、StringReader を格納テキストの復元に使用できるようになります。
ReadOutput = new System.IO.StringReader(WriteOutput.ToString());
string capturedOutput = ReadOutput.ReadToEnd();
接続オブジェクトのリダイレクトの委任は、必要に応じて何度でも変更できます。以下のコードは、conn の設定を既定のリダイレクトの委任に戻します。
conn.OutputRedirectionDelegate = CacheConnection.DefaultOutputRedirection;
Caché の Read 文からの入力も、InputRedirection 委任を使用して同様にリダイレクトできます。
実用的な例は、bookdemos サンプル・プログラムの Proxy_7_Redirection() メソッドを参照してください (“Caché NET サンプル・プログラム” を参照)。