Update 関数
Update 関数がオブジェクトを呼び出すと、新しいデータと状態に基づいて、オブジェクトがエンジンに再評価され、再評価されます。 オブジェクトの型は TypedXmlDocument または .NET クラス、 DataConnection 、 TypedDataTable のいずれかです。
このトピックで説明するように、 Update 関数を使用してエンジンのパフォーマンスを向上させ、無限ループシナリオを回避することもできます。
通常、 Assert を使用してルール エンジンの作業メモリに新しいオブジェクトを配置し、 Update を 使用して作業メモリ内の既存のオブジェクトを更新します。 新しいオブジェクトをアサートすると、すべてのルールの条件が評価されます。 既存のオブジェクトを更新すると、更新されたファクトを使用する条件のみ再評価され、これらの条件が true に評価された場合にアクションが議題に追加されます。
例として 2 つのルールを示します。 オブジェクト ItemA と ItemB が既に作業メモリに存在するとします。 ルール 1 は ItemA の Id プロパティを評価し、ItemB に Id プロパティを設定し、変更後に ItemB を再評価します。 ItemB が再アサートされると、新しいオブジェクトとして扱われ、エンジンは述語またはアクションでオブジェクト ItemB を使用するすべてのルールを再評価します。 これにより、規則 2 が規則 1 で設定されている ItemB.Id の新しい値に対して再評価されます。 ルール 2 は、最初に評価されるときに失敗した可能性がありますが、2 回目の評価時に true と評価されます。
IF ItemA.Id == 1
THEN ItemB.Id = 2
Assert(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
オブジェクトを作業メモリに再度アサートする機能により、ユーザーは、順行連鎖シナリオでの動作を明示的に制御できます。 しかし、この例では再アサーションの副作用により、ルール 1 も再評価されます。 ItemA.Id が変更されていないため、ルール 1 は再び true に評価され、Assert(ItemB) アクションが再度発生します。 その結果、無限ループが発生します。
注意
ルールの再評価の既定の最大ループ数は 2^32 です。 特定のルールでは、ポリシーの実行が長時間続く可能性があります。 ポリシー バージョンの [Maximum Execution Loop Depth]\(最大実行ループ深度 \) プロパティを調整することで、カウントを減らすことができます。
無限ループを作成せずにオブジェクトを再アサートできる必要があり、 Update 関数はこの機能を提供します。 Reassert と同様に、 Update 関数は関連付けられたオブジェクト インスタンスの 取り消 しと アサート を実行します。これはルール アクションから変更されていますが、次の 2 つの主な違いがあります。
そのインスタンスの種類が述語ではなくアクションのみで使用されるルールでは、議題に含まれるアクションが議題に維持されます。
そのインスタンスの種類をアクションのみで使用するルールは再評価されません。
したがって、述語のみ、または述語とアクションの両方でインスタンスの種類を使用するルールが再評価され、そのアクションが議題に適切に追加されます。
前の例を Update 関数を使用するように変更すると、ルール 2 の条件で ItemB が使用されるため、ルール 2 のみが再評価されます。 ItemB はルール 1 のアクションでのみ使用されるため、ルール 1 は再評価されず、ループ シナリオはなくなります。
IF ItemA.Id == 1
THEN ItemB.Id = 2
Update(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
しかし、まだループ シナリオが発生する可能性があります。 たとえば、次の規則を考えてみましょう。
IF ItemA.Id == 1
THEN ItemA.Value = 20
Update(ItemA)
ItemA は述語で使用されるため、ItemA で Update が呼び出されると再評価されます。 ItemA.Id の値が他の場所で変更されていない場合、ルール 1 は引き続き true に評価され、A で Update が再度呼び出されます。ルール デザイナーは、このようなループ シナリオが作成されないようにする必要があります。
この場合の適切なアプローチは、ルールの特性により異なります。 前の例の問題を解決するための簡単なメカニズムを次に示します。
Update 関数は、Assert、Retract、または RetractByType 関数と同様に、 クラスへの参照を持つビジネス ルール Composer で使用できます。
IF ItemA.Id == 1 and ItemA.Value != 20
THEN ItemA.Value = 20
Update(ItemA)
ItemA.Value にチェックを追加すると、ルール 1 のアクションが初めて実行された後に、ルール 1 が再び true に評価されなくなります。
例として 2 つのルールを示します。 とします。 ルール 1 では注文書メッセージの項目の合計数を評価します。合計数が 10 以上である場合、ルール 2 により状態は "Needs approval" に設定されます。
IF 1 == 1
THEN ProcessPO.Order:/Order/Items/TotalCount = (ProcessPO.Order:/Order/Items/TotalCount + ProcessPO:/Order/Items/Item/Count)
IF ProcessPO.Order:/Order/Items/TotalCount >= 10
THEN ProcessPO.Order:/Order/Status = "Needs approval"
このポリシーへの入力として次の発注書 (PO) メッセージを渡すと、アイテムの合計数が 14 であっても、状態が "承認が必要" に設定されていないことに気付きます。 これは、 TotalCount フィールドの値が 0 の場合に rule2 が最初にのみ評価され、使用可能な合計数が更新されるたびにルールが評価されないためです。 TotalCount が更新されるたびに条件を再評価するには、変更されたノード (TotalCount) の親ノード (Items) で Update 関数を呼び出す必要があります。 ルール 1 を次に示すように変更し、もう一度テストすると、Status フィールドの値は "Needs Approval" に設定されます。
<ns0:Order xmlns:ns0="http://ProcessPO.Order">
<Items>
<Item>
<Id>ITM1</Id>
<Count>2</Count>
</Item>
<Item>
<Id>ITM2</Id>
<Count>5</Count>
</Item>
<Item>
<Id>ITM3</Id>
<Count>7</Count>
</Item>
<TotalCount>0</TotalCount>
</Items>
<Status>No approval needed</Status>
</ns0:Order>
変更された 規則 1 は次のとおりです。
IF 1 == 1
THEN ProcessPO.Order:/Order/Items/TotalCount = (ProcessPO.Order:/Order/Items/TotalCount + ProcessPO:/Order/Items/Item/Count) AND
Update(ProcessPO.Order:/Order/Items)
TypedDataTable で Update が呼び出された場合、関連付けられているすべての TypedDataRows でエンジンによって Update が呼び出されます。 個々 の TypedDataRows で更新を呼び出すこともできます。
DataConnection の更新はサポートされていません。 代わりに Assert を使用してください。