情報システムのほぼすべての開発者が、実装中に初期データを生成するタスクに直面していると言っても過言ではないと思います。
Caché開発者には、初期データを初期化するためのいくつかの標準的なアプローチがあります。
- 外部ファイルから参照クラスのデータをロードする、
- オンラインサービスからデータを受信する、
- グローバルファイルからの静的データのインポート、
- 「有線」からデータコードに初期データを作成するクラスメソッドの実行。
静的データ、小さな参照、またはシステムの構成データの初期化には、別の方法があります。これについては記事で説明します。
Cachéには、XMLデータブロックをクラスコード(XDATAブロック)に含める機能があります。 通常、このデータは、クラスとともにZenページフォームおよびZenレポートに関するデータを格納するために使用されます 。 これらのブロックでは、永続クラスの初期データを完全に保存することもできます。
XDataからの逆シリアル化
1つのプロパティを持つ単純なストアドクラスの例を考えてみましょう。 これは名前を持つリージョンのクラスになります-ディレクトリの典型的な例です。
Cachéのこのクラスのコードは次のとおりです。
クラスmap.Region Extends%Persistent
{
///名前
プロパティ 名 As%String ;
}
XML形式の初期データをXDataブロックのクラスに追加します。
Xdataの 入力
{
< xml >
< アイテム >
< 名前 >クラスノヤルスク地域</ / 名前 >
</ アイテム >
< アイテム >
< 名前 >スヴェルドロフスク地域</ / 名前 >
</ アイテム >
< アイテム >
< 名前 >ハバロフスク地方</ / 名前 >
</ アイテム >
</ xml >
}
このデータをクラスからロードするために、Populateクラスメソッドを追加します。 さらに、XMLデータを操作するには、クラスをXML対応にする必要があります。%XML.Adaptorクラスも継承リストに追加します。 その結果、変換されたクラスコードは次のようになります。
クラスmap.Region Extends ( %Persistent 、 %XML.Adaptor )
{
///名前
プロパティ 名 As%String ;
ClassMethod Populate() As%Status
{
#dim sc As %Status = $$$ OK
//既存のクラスデータをクリアします
s sc = .. %DeleteExtent ()
$$$ ISERR (sc) が scを 終了する 場合
//コンパイルされたクラスライブラリからXDataブロックのxmlデータをロードします
#dim stream As %Stream.Object = ## class ( %Dictionary.CompiledXData )。 %OpenId (.. %ClassName (1)_ "||" _ "populate" )。 データ
// XMLリーダーのインスタンスを作成します
#dim reader As %XML.Reader = ## class ( %XML.Reader )。 %新規 ()
//リーダーでxmlストリームを開きます
sc =リーダーを 設定し ます。 OpenStream (ストリーム、 「リテラル」 )
$$$ ISERR (sc) が scを 終了する 場合
//リーダーにクラスデータを探す要素を伝えます
リーダーを行います。 相関 ( "item" 、.. %ClassName (1))
#dim obj as %Persistent
//クラスループでロードする
リーダー ながら 。 次 (.obj、.sc)
{
$$$ ISERR (sc)が 終了した場合
// xmlインスタンスからの読み取りをデータベースに保存します
sc = objを 設定し ます。 %保存 ()
$$$ ISERR (sc)が 終了した場合
obj = ""を 設定します
}
scを 終了
}
Xdataの 入力
{
< xml >
< アイテム >
< 名前 >クラスノヤルスク地域</ / 名前 >
</ アイテム >
< アイテム >
< 名前 >スヴェルドロフスク地域</ / 名前 >
</ アイテム >
< アイテム >
< 名前 >ハバロフスク地方</ / 名前 >
</ アイテム >
</ xml >
}
}
コードからわかるように、すべての作業は%XML.Readerクラスによって行われ、XMLから「オブジェクト」データを読み取ることができます。
デプロイ中にクラスにデータをロードするには、Populateクラスのメソッドを実行するだけで十分です。
w ##クラス ( map.Region )。 人口 ()
クラスインスタンスが実際に作成されていることを確認してください。 ターミナルのSQLシェルでクエリを実行してみましょう。
XMLDEPLOY>d $System.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: <<nothing>>. Enter q to quit, ? for help. XMLDEPLOY>>select * from map.Region 1. select * from map.Region ID Name 1 2 3 3 Rows(s) Affected statement prepare time: 0.9125s, elapsed execute time: 0.0687s. --------------------------------------------------------------------------- XMLDEPLOY>>quit XMLDEPLOY>
XData Fill
明らかに、XDataブロックは「手動」で埋めることができます。 クラス内にオブジェクトがほとんどない場合、これは便利です。 しかし、それらがたくさんある場合、プログラムはそれを行うことができます。
%XML.Writerクラスを使用します。これにより、クラスインスタンスをXMLにシリアル化できます。
これを行うには、クラスにシリアル化メソッドを追加します。
ClassMethod SerializeToFile( file as%String ) as%Status
{
#dim sc ( %ステータス として)
%dim.wr としての #dim wr
set wr = ## class ( %XML.Writer )。 %新規 ()
//ファイルを出力デバイスとしてインストールします
sc = wrを 設定し ます。 Output IsFile (ファイル) $$$ ISERR (sc) が scを 終了する 場合
//ルートタグを開きます
sc = wrを 設定し ます。 RootElement ( "xml" ) $$$ ISERR (sc) が scを 終了する 場合
#dim rset as %ResultSet
//クラスのすべてのオブジェクトを含むエクステントリクエストを実行します
set rset = ## class ( %ResultSet )。 %新規 ( "map.Region:Extent" )
rsetを実行します。 実行 ()
#dim obj
while (rset。Next ()) {
set obj = ##クラス ( map.Region )。 %OpenId (rset。 データ ( "ID" ))
//オブジェクトをシリアル化します
sc = wrを 設定し ます。 オブジェクト (obj)
$$$ ISERR (sc)が 終了した場合
}
$$$ ISERR (sc) が scを 終了する 場合
//ルートタグを閉じます
sc = wrを 設定し ます。 EndRootElement ()
scを 終了
}
このメソッドは、XMLでシリアル化されたクラスのすべてのオブジェクトをファイルに出力します。
ターミナルでメソッドを実行しましょう:
XMLDEPLOY>D $System.OBJ.DisplayError(##class(map.Region).SerializeToFile("C:\cache\region.xml")) XMLDEPLOY>
そして、任意のエディター/ビューアーでファイルを開きます:
結果のXMLは、XDataブロックに簡単に挿入できます。
合計
同様に、展開中に初期データの入力を必要とするすべてのクラスに同様のメソッドを提供できます。 その結果、上記の手法を使用して、初期データは、技術的に高度なXML形式で必要なクラスとともに保存されます。 クラスコードのみをクライアントに提供でき、Populateメソッドを使用して初期データを生成できます。 しかし、クラスが互いに関連している場合はどうでしょうか? このシナリオと他のシナリオについては、記事の第2部で検討します。 続行するには...