永続オブジェクトを使用した作業
%PersistentOpens in a new tab クラスは、保存可能な (ディスクに書き込める) オブジェクトに対応した API です。ここでは、この API の使用方法について説明します。このトピックの情報は、%PersistentOpens in a new tab のすべてのサブクラスに適用されます。
このトピックで示されているサンプルのほとんどが、Samples-Data サンプル (https://github.com/intersystems/Samples-DataOpens in a new tab) からのものです。(例えば) SAMPLES という名前の専用ネームスペースを作成し、そのネームスペースにサンプルをロードすることをお勧めします。一般的な手順は、"サンプルのダウンロード" を参照してください。
オブジェクトの保存
オブジェクトをデータベースに保存するには、そのオブジェクトの %Save() メソッドを呼び出します。以下に例を示します。
Set obj = ##class(MyApp.MyClass).%New()
Set obj.MyValue = 10
Set sc = obj.%Save()
%Save() メソッドは、保存操作が成功したか失敗したかを示す %StatusOpens in a new tab 値を返します。例えば、オブジェクトが無効なプロパティ値を持つ場合や一意性に違反した場合、エラーが発生することがあります。"オブジェクトの検証" を参照してください。
オブジェクトで %Save() を呼び出すと、保存されているオブジェクトからアクセスできる、すべての変更済みオブジェクトが自動的に保存されます。つまり、すべての埋め込みオブジェクト、コレクション、ストリーム、参照オブジェクト、およびオブジェクトに関与するリレーションシップが必要に応じて自動的に保存されます。保存操作全体が 1 つのトランザクションとして実行されます。保存できないオブジェクトがある場合、トランザクション全体が失敗し、ロール・バックされます (ディスクには変更がなく、すべてのメモリ内オブジェクト値が、%Save() メソッドが呼び出される前の値に戻ります)。
初めてオブジェクトが保存されるとき、%Save() メソッドの既定の動作は、自動的にそのオブジェクトにオブジェクト ID 値を割り当てます。この ID 値は後に、データベース内でオブジェクトの検索時に使用されます。既定の場合、ID は、$Increment 関数を使用して生成されます。または、クラスは、idkey index を持つプロパティ値に基づくユーザ提供オブジェクト ID を使用できます (この場合、プロパティ値は、|| 文字列を含むことはできません)。一度割り当てられると、(これがユーザ提供の ID でも) 特定のオブジェクト・インスタンスに対するオブジェクト ID 値を変更できません。
%Id() メソッドを使用して、保存されたオブジェクトに対するオブジェクト ID を検索できます。
// Open person "22"
Set person = ##class(Sample.Person).%OpenId(22)
Write "Object ID: ",person.%Id(),!
%Save() メソッドが行う詳細は、以下のとおりです。
-
最初に、SaveSet として知られる一時的な構造を構築します。SaveSet は単純なグラフで、保存されたオブジェクトから到達可能なすべてのオブジェクトに対する参照を含みます (一般に、オブジェクト・クラス A に、別のオブジェクト・クラス B の値を保持しているプロパティがあれば、A のインスタンスは B のインスタンスに到達できます)。SaveSet の目的は、関連するオブジェクトの複雑なセットに関連する保存操作が、可能な限り効果的に実行できるようにすることです。SaveSet は、オブジェクト間の保存順序の依存関係も解決します。
各オブジェクトが SaveSet に追加されると、その %OnAddToSaveSet() コールバック・メソッドが存在する場合は呼び出されます。
-
SaveSet 内の各オブジェクトを順番に検索し、それらが変更されていないかをチェックします (つまり、オブジェクトを開いた後で、または最後に保存されて以降、そのプロパティ値が変更されていないかをチェックします)。変更されているオブジェクトがある場合、そのオブジェクトは保存されます。
-
保存される前に、変更された各オブジェクトは検証されます (そのプロパティ値がテストされます。その %OnValidateObject() メソッドが存在する場合は呼び出され、一意制約がテストされます)。オブジェクトが有効な場合、保存操作が継続します。無効なオブジェクトがある場合は、%Save() の呼び出しが失敗し、現在のトランザクションがロール・バックされます。
-
各オブジェクトの保存前、または保存後、%OnBeforeSave() メソッドと %OnAfterSave() コールバック・メソッドが存在する場合は実行されます。同様に、定義されている BEFORE INSERT、BEFORE UPDATE、AFTER INSERT、および AFTER UPDATE のトリガがある場合は、それらも呼び出されます。
これらのコールバックおよびトリガに Insert 引数が渡されます。この引数は、オブジェクトが挿入されているか (初めての保存の場合)、または更新されているかを示すものです。
これらのコールバック・メソッドまたはトリガのいずれかが失敗した場合 (エラー・コードを返した場合)、%Save() への呼び出しは失敗し、現在のトランザクションがロール・バックされます。
-
最後に、%OnSaveFinally() コールバック・メソッドが存在する場合は呼び出されます。
このコールバック・メソッドは、トランザクションが完了し、保存のステータスが確定した後に呼び出されます。
現在のオブジェクトが変更されていない場合、ディスクには %Save() メソッドによって書き込みは行われません。オブジェクトの保存は必要がなく、そのため保存は失敗しないため、成功が返されます。 実際のところ、%Save() の返り値では、保存操作で要求がすべて実行されたか、それとも要求どおりには実行されなかったか (および明確にではなく何かがディスクに書き込まれたかどうか) が示されます。
Rollback
%Save() メソッドは、SaveSet 内のすべてのオブジェクトを単独のトランザクションとして自動的に保存します。これらのオブジェクトのいずれかの保存が失敗した場合、トランザクション全体がロール・バックされます。このロールバックの場合、InterSystems IRIS は以下を実行します。
-
割り当てられた ID を元に戻します。
-
削除された ID を回復します。
-
変更されたビットを回復します。
-
正常にシリアル化されたオブジェクトに対して、%OnRollBack() コールバック・メソッドを呼び出します (実装されている場合)。
InterSystems IRIS は、正常にシリアル化されていないオブジェクト (つまり、無効なオブジェクト) に対しては、このメソッドを呼び出しません。
オブジェクトとトランザクションの保存
前述したように、%Save() メソッドは、SaveSet 内のすべてのオブジェクトを単独のトランザクションとして自動的に保存します。これらのオブジェクトのいずれかの保存が失敗した場合、トランザクション全体がロール・バックされます。
複数の関連しないオブジェクトを 1 つのトランザクションとして保存する場合は、%Save() の呼び出しを 1 つの明示的なトランザクション内にまとめる必要があります。つまり、TSTART コマンドを使用してトランザクションを開始し、TCOMMIT コマンドを使用してトランザクションを終了する必要があります。
例 :
// start a transaction
TSTART
// save first object
Set sc = obj1.%Save()
// save second object (if first was save)
If ($$$ISOK(sc)) {
Set sc = obj2.%Save()
}
// if both saves are ok, commit the transaction
If ($$$ISOK(sc)) {
TCOMMIT
}
上記の例では、注意すべきことが 2 つあります。
保存したオブジェクトの存在のテスト
特定のオブジェクト・インスタンスがデータベース内に保存されているかをテストするには、2 つの基本的な方法があります。
これらの例では、ID は整数です (InterSystems IRIS が既定で生成する ID)。ID がオブジェクトの固有プロパティに基づくようにクラスを定義することもできます。
ObjectScript によるオブジェクトの存在のテスト
%ExistsId() クラス・メソッドは、指定された ID を確認します。指定されたオブジェクトがデータベース内に存在する場合は True (1) の値を返し、それ以外の場合は False (0) を返します。これは、%PersistentOpens in a new tab から継承されたすべてのクラスで使用できます。以下に例を示します。
Write ##class(Sample.Person).%ExistsId(1),! // should be 1
Write ##class(Sample.Person).%ExistsId(-1),! // should be 0
ここでは、最初の行が 1 を返します。これは、Sample.Person が %PersistentOpens in a new tab を継承していて、SAMPLES データベースは、このクラスにデータを提供するためです。
%Exists() メソッドも使用できます。このメソッドには、ID ではなく OID が必要になります。OID はデータベースに対して一意の永続識別子で、オブジェクトの ID とクラス名の両方が含まれます。詳細は、"保存したオブジェクトの識別子 : ID および OID" を参照してください。
SQL によるオブジェクトの存在のテスト
保存したオブジェクトの存在を SQL でテストするには、指定した ID と一致する %ID フィールドを持つ行を選択する SELECT 文を使用します (保存したオブジェクトの identity プロパティは、%ID フィールドとして投影されます)。
例えば、以下のように埋め込み SQL を使用します。
&sql(SELECT %ID FROM Sample.Person WHERE %ID = '1')
Write SQLCODE,! // should be 0: success
&sql(SELECT %ID FROM Sample.Person WHERE %ID = '-1')
Write SQLCODE,! // should be 100: not found
ここでは、最初のケースは結果として 0 の SQLCODE を返します (成功を意味します)。これは、Sample.Person が %PersistentOpens in a new tab を継承していて、SAMPLES データベースは、このクラスにデータを提供するためです。
2 つ目のケースは、文の実行は成功したもののデータは返されないことを示す SQLCODE 100 になります。システムは 0 未満の ID を自動的には生成しないため、このように想定されます。
埋め込み SQL の詳細は、"埋め込み SQL の使用法" を参照してください。SQLCODE の詳細は、"InterSystems IRIS エラー・リファレンス" の "SQLCODE 値とエラー・メッセージ" を参照してください。
保存したオブジェクトのオープン
オブジェクトを開く (ディスクからメモリにオブジェクト・インスタンスをロードする) には、以下のように %OpenId() メソッドを使用します。
classmethod %OpenId(id As %String,
concurrency As %Integer = -1,
ByRef sc As %Status = $$$OK) as %ObjectHandle
以下はその説明です。
-
id は、開くオブジェクトの ID です。
この例では、ID は整数です。ID がオブジェクトの固有プロパティに基づくようにクラスを定義することもできます。
-
concurrency は、オブジェクトを開くために使用する並行処理レベル (ロック) です。
-
参照渡しの sc は、%StatusOpens in a new tab の値です。この値は、呼び出しが成功したか、失敗したかを表します。
指定のオブジェクトを開くことができる場合は、このメソッドが OREF を返します。オブジェクトが見つからない場合やオブジェクトが開けない場合は、NULL 値 ("") が返されます。
例 :
// Open person "10"
Set person = ##class(Sample.Person).%OpenId(10)
Write "Person: ",person,! // should be an object reference
// Open person "-10"
Set person = ##class(Sample.Person).%OpenId(-10)
Write "Person: ",person,! // should be a null string
%Open() メソッドも使用できます。このメソッドには、ID ではなく OID が必要になります。OID はデータベースに対して一意の永続識別子で、オブジェクトの ID とクラス名の両方が含まれます。詳細は、"保存したオブジェクトの識別子 : ID および OID" を参照してください。
オブジェクトが開くときに実行される追加の処理を行うには、%OnOpen() および %OnOpenFinally() のコールバック・メソッドを定義します。詳細は、"コールバック・メソッドの定義" を参照してください。
%OpenId() に対する複数の呼び出し
%OpenId() が 1 つの InterSystems IRIS プロセス内で同じ ID と同じオブジェクトに対して複数回呼び出された場合、メモリに作成されるオブジェクト・インスタンスは 1 つのみです。それ以降の %OpenId() の呼び出しはすべて、既にメモリにロードされているオブジェクトへの参照が返されます。
例えば、同じオブジェクトへの複数回の %OpenId() 呼び出しを特徴とする以下のクラスを見てみましょう。
Class User.TestOpenId Extends %RegisteredObject
{
ClassMethod Main()
{
set A = ##class(Sample.Person).%OpenId(1)
write "A: ", A.Name
set A.Name = "David"
write !, "A after set: ", A.Name
set B = ##class(Sample.Person).%OpenId(1)
write !, "B: ", B.Name
do ..Sub()
job ..JobSub()
hang 1
write !, "D in JobSub: ", ^JobSubD
kill ^JobSubD
kill A, B
set E = ##class(Sample.Person).%OpenId(1)
write !, "E:", E.Name
}
ClassMethod Sub()
{
set C = ##class(Sample.Person).%OpenId(1)
write !, "C in Sub: ", C.Name
}
ClassMethod JobSub()
{
set D = ##class(Sample.Person).%OpenId(1)
set ^JobSubD = D.Name
}
}
Main() メソッドを呼び出すと、以下のような結果になります。
-
最初の %OpenId() 呼び出しは、インスタンス・オブジェクトをメモリにロードします。A 変数はこのオブジェクトを参照しており、この変数によって、ロードされたオブジェクトを変更できます。
set A = ##class(Sample.Person).%OpenId(1) write "A: ", A.Name
A: Uhles,Norbert F.
set A.Name = "David" write !, "A after set: ", A.Name
A after set: David
-
2 つ目の %OpenId() 呼び出しは、データベースからオブジェクトを再ロードすることも、変数 A を使用して加えられた変更を上書きすることもありません。その代わり、変数 B が変数 A と同じオブジェクトを参照します。
set B = ##class(Sample.Person).%OpenId(1) write !, "B: ", B.Name
B: David
-
3 つ目の %OpenId() 呼び出しは、Sub() メソッド内にあり、これも既にロードされているオブジェクトを参照します。このメソッドは、Main() メソッドと同じ InterSystems IRIS プロセスに含まれています。変数 C は、変数 A および変数 B と同じオブジェクトを参照します。ただし、変数 A と B はこのメソッドのスコープ内では使用できません。Sub() メソッドの最後に、プロセスは Main() メソッドに戻り、変数 C は破棄され、変数 A および B はスコープ内に戻ります。
do ..Sub()
ClassMethod Sub() { set C = ##class(Sample.Person).%OpenId(1) write !, "C in Sub: ", C.Name }
C in Sub: David
-
4 つ目の %OpenId() 呼び出しは、JobSub() メソッド内にあり、JOB コマンドを使用して別個の InterSystems IRIS プロセスで実行されます。この新しいプロセスは、新しいインスタンス・オブジェクトをメモリにロードし、変数 D でこの新しいオブジェクトを参照します。
job ..JobSub() hang 1 write !, "D in JobSub: ", ^JobSubD kill ^JobSubD
ClassMethod JobSub() { set D = ##class(Sample.Person).%OpenId(1) set ^JobSubD = D.Name }
D in JobSub: Uhles,Norbert F.
-
5 つ目の %OpenId() 呼び出しが実行されるのは、ロード済みのオブジェクトを元のプロセスで参照している変数 (A および B) をすべて削除し、それによってそのオブジェクトをメモリから削除した後です。直前の %OpenId() 呼び出しと同様に、この呼び出しも新しいインスタンス・オブジェクトをメモリにロードし、変数 E でこのオブジェクトを参照します。
kill A, B set E = ##class(Sample.Person).%OpenId(1) write !, "E:", E.Name
E: Uhles,Norbert F.
複数回ロードされるオブジェクトを強制的に再ロードするには、%Reload() メソッドを使用します。オブジェクトを再ロードすると、そのオブジェクトに対する未保存の変更は元に戻されます。以前に割り当てられていた変数は、再ロードされたバージョンを参照します。以下に例を示します。
set A = ##class(Sample.Person).%OpenId(1)
write "A: ", A.Name // A: Uhles,Norbert F.
set A.Name = "David"
write !, "A after set: ", A.Name // David
set B = ##class(Sample.Person).%OpenId(1)
write !, "B before reload: ", B.Name // David
do B.%Reload()
write !, "B after reload: ", B.Name // Uhles,Norbert F.
write !, "A after reload: ", A.Name // Uhles,Norbert F.
並行処理
%OpenId() メソッドは、入力としてオプションの concurrency 引数を取ります。この引数は、オブジェクト・インスタンスを開くために使用する並行処理レベル (ロックのタイプ) を指定します。
%OpenId() メソッドがオブジェクトのロックを取得できない場合、メソッドは失敗します。
オブジェクトに対する現在の並行処理レベルの設定を上げ下げするには、そのオブジェクトを %OpenId() で再度開いて別の並行処理レベルを指定します。以下はその例です。
set person = ##class(Sample.Person).%OpenId(6,0)
並行処理レベル 0 でperson を開き、以下のようにして並行処理レベルを事実上 4 まで引き上げます。
set person = ##class(Sample.Person).%OpenId(6,4)
並行処理レベル 3 (共有保持ロック) または 4 (共有排他ロック) を指定すると、オブジェクトを開くときにそのオブジェクトが強制的に再ロードされます。可能なオブジェクト並行処理レベルの詳細は、"オブジェクト同時処理のオプション" を参照してください。
スウィズリング
永続オブジェクトのインスタンスを開いて (メモリにロードして)、そのインスタンスが参照するオブジェクトを使用する場合、この参照されるオブジェクトは自動的に開かれます。このプロセスをスウィズリングといいます。また、遅延ロードということもあります。
例えば、以下のコードは Sample.Employee オブジェクトのインスタンスを開き、ドット構文を使用して関連する Sample.Company オブジェクトを自動的にスウィズルします (開きます)。
// Open employee "101"
Set emp = ##class(Sample.Employee).%OpenId(101)
// Automatically open Sample.Company by referring to it:
Write "Company: ",emp.Company.Name,!
オブジェクトをスウィズルすると、オブジェクトは、それをスウィズルするオブジェクトの並行処理値ではなく、それが属するクラスの既定の並行処理値を使用して開かれます。"オブジェクト同時処理のオプション" を参照してください。
スウィズルされたオブジェクトは、それを参照するオブジェクトや変数がなくなるとすぐに、メモリから削除されます。
オブジェクトを手動でスウィズルしたり、オブジェクトがスウィズルされているかどうか確認したい場合があります。これらのタスクのどちらにも、プロパティ・メソッド <prop>GetSwizzled() を使用できます。前述の例の Company プロパティの場合は、CompanyGetSwizzled() を呼び出すと、Company オブジェクトがスウィズルされ、オブジェクトの OREF が返されます。CompanyGetSwizzled(1) のように、1 を引数として渡すと、メソッドはオブジェクトの OREF を返しますが、オブジェクトが既にスウィズルされている場合に限られます。そうでない場合、NULL の OREF が返されます。
例として、ターミナルでは以下のようになります。
USER>set emp = ##class(Sample.Employee).%OpenId(102)
USER>set co = emp.CompanyGetSwizzled(1)
USER>if (co = "") {write "Company is not swizzled"} else {write co.Name}
Company is not swizzled
USER>set co = emp.CarGetSwizzled()
USER>if (co = "") {write "Company is not swizzled"} else {write co.Name}
Acme Company, Inc.
保存された値の読み取り
永続オブジェクトのインスタンスを開き、そのプロパティを変更したと仮定します。また、そのオブジェクトを保存する前に、データベースに保存された元の値を表示するとします。これを実行する最も簡単な方法は、生成されたプロパティ・メソッドの 1 つ、具体的には propertynameGetStored() を使用することです。以下に例を示します。
// Open person "1"
Set person = ##class(Sample.Person).%OpenId(1)
Write "Original value: ",person.Name,!
// modify the object
Set person.Name = "Black,Jimmy Carl"
Write "Modified value: ",person.Name,!
// Now see what value is on disk
Set id = person.%Id()
Set name = ##class(Sample.Person).NameGetStored(id)
Write "Disk value: ",name,!
もう 1 つの簡単なオプションは、埋め込み SQL 文を使用することです (SQL は、メモリ内のオブジェクトではなく、常にデータベースに対して実行されます)。NameGetStored() を呼び出す代わりに、以下を使用します。
// Now see what value is on disk
&sql(SELECT Name INTO :name
FROM Sample.Person WHERE %ID = :id)
If (SQLCODE = 0) {Write "Disk value: ",name,!}
保存したオブジェクトの削除
永続インタフェースには、データベースからオブジェクトを削除するためのメソッドがあります。
%DeleteId() メソッド
%DeleteId() メソッドは、データベース内に保存されているオブジェクトを削除します。これには、オブジェクトに関連付けられているストリーム・データも含まれます。このメソッドのシグニチャは、以下のとおりです。
classmethod %DeleteId(id As %String, concurrency As %Integer = -1) as %Status
以下はその説明です。
-
id は、開くオブジェクトの ID です。
この例では、ID は整数です。ID がオブジェクトの固有プロパティに基づくようにクラスを定義することもできます。
-
concurrency は、オブジェクト削除時に使用する並行処理レベル (ロック) です。
以下に例を示します。
Set sc = ##class(MyApp.MyClass).%DeleteId(id)
%DeleteId() は、オブジェクトが削除されたか否かを示す %StatusOpens in a new tab 値を返します。
オブジェクトが削除される前に、%OnDelete() コールバック・メソッドが存在していれば、%DeleteId() はそれを呼び出します。%OnDelete() は %StatusOpens in a new tab 値を返します。%OnDelete() がエラー値を返した場合、オブジェクトは削除されず、現在のトランザクションがロール・バックされ、%DeleteId() はエラー値を返します。
オブジェクトが削除された後に、%OnAfterDelete() コールバック・メソッドが存在していれば、%DeleteId() はそれを呼び出します。この呼び出しは、%DeleteData() がエラーを返さない限り、%DeleteData() が呼び出された直後に行われます。%OnAfterDelete() がエラーを返す場合、現在のトランザクションはロール・バックされ、%DeleteId() はエラー値を返します。
最後に、%DeleteId() は、%OnDeleteFinally() コールバック・メソッドが存在する場合は呼び出します。このコールバック・メソッドは、トランザクションが完了し、削除のステータスが確定した後に呼び出されます。
%DeleteId() メソッドは、メモリ内のオブジェクト・インスタンスには効果がありません。
%Delete() メソッドも使用できます。このメソッドには、ID ではなく OID が必要になります。OID はデータベースに対して一意の永続識別子で、オブジェクトの ID とクラス名の両方が含まれます。詳細は、"保存したオブジェクトの識別子 : ID および OID" を参照してください。
%DeleteExtent() メソッド
%DeleteExtent() メソッドは、エクステント内のすべてのオブジェクト (およびオブジェクトのサブクラス) を削除します。具体的には、エクステント全体を反復処理して、オブジェクトの各インスタンスで %Delete() メソッドを起動します。既定では、すべてのインスタンスが正常に削除されると、%KillExtent() メソッドを呼び出します。
このメソッドのシグニチャは、以下のとおりです。
classmethod %DeleteExtent(concurrency As %Integer = -1, ByRef deletecount, ByRef instancecount, pInitializeExtent As %Integer = 1, Output errorLog As %Status) as %Status
以下はその説明です。
-
concurrency は、オブジェクト削除時に使用する並行処理レベル (ロック) です。
-
deletecount は、削除されるインスタンスの数です。
-
instancecount は、インスタンスの元の数です。
-
pInitializeExtent は、エクステントが空の場合に %KillExtent() を呼び出すかどうかを決定します。
-
0 の値は、%KillExtent() が呼び出されないことを意味します。一部の空のグローバルと ID カウンタ (存在する場合) は残る場合があります。
-
1 の値は、%KillExtent() が呼び出されるが、既定のストリーム・グローバルは削除されないことを意味します。これが既定値です。
-
2 の値は、%KillExtent() が呼び出され、既定のストリーム・グローバルが削除されることを意味します。
Note:エクステントにより使用されるグローバルがエクステントにより排他的に使用されない場合、一部のグローバルは %KillExtent() が呼び出されても残る場合があります。
-
-
errorLog は、該当するエラーを返すために使用されます。
以下に例を示します。
Set sc = ##class(MyApp.MyClass).%DeleteExtent(-1, .deletecount, .instancecount, 2, .errorLog)
%KillExtent() メソッド
%KillExtent() メソッドは、クラスのエクステント、そのサブエクステント (サブクラス)、およびその子エクステント (そのクラスの子リレーションシップを持つクラスのエクステント) を格納するグローバルを直接削除します。既定のストリーム・ストレージ・グローバルはオプションで削除されます。%KillExtent() により %Delete() メソッドは呼び出されず、参照整合性アクションも実行されません。
このメソッドのシグニチャは、以下のとおりです。
classmethod %KillExtent(pDirect As %Integer = 1, killstreams As %Boolean = 0) as %Status
以下はその説明です。
-
pDirect は、ファイリング・タイムスタンプも ^OBJ.DSTIME グローバルから削除されるかどうかを決定します。これは、InterSystems IRIS Business Intelligence で使用されます。"キューブの最新状態の維持" を参照してください。デフォルトは 1 です。
-
killstreams は、既定のストリーム・グローバルが削除されるかどうかを決定します。デフォルトは 0 です。
以下に例を示します。
Set sc = ##class(MyApp.MyClass).%KillExtent(1, 0)
%KillExtent() は、開発環境でのみ直接呼び出す必要があり、実際のアプリケーションでは使用しないでください。%KillExtent() は、制約やユーザ実装のコールバックを回避するため、データ整合性の問題を引き起こす可能性があります。アプリケーションでエクステント内のすべてのオブジェクトを削除する必要がある場合は、代わりに %DeleteExtent() を使用してください。
オブジェクト識別子のアクセス
オブジェクトが保存されている場合、そのオブジェクトには ID と OID があります。これらは、ディスクで使用する永久識別子です。オブジェクトの OREF があれば、その OREF を使用して、これらの識別子を取得できます。
OREF に関連付けられた ID を調べるには、オブジェクトの %Id() メソッドを呼び出します。以下に例を示します。
write oref.%Id()
OREF に関連付けられた OID を調べる場合は、以下の 2 つの選択肢があります。
-
オブジェクトの %Oid() メソッドを呼び出します。以下に例を示します。
write oref.%Oid()
-
オブジェクトの %%OID プロパティにアクセスします。このプロパティ名には % 文字が含まれているため、その名前を二重引用符で囲む必要があります。以下に例を示します。
write oref."%%OID"