更新功能
叫用 Update 函式時,系統會根據新的資料和狀態,將物件重新組譯為要重新評估的引擎。 物件的類型可以是 TypedXmlDocument 或 .NET 類別或 DataConnection 或 TypedDataTable。
您也可以使用 Update 函式來改善引擎效能,並防止無止盡的迴圈案例,如本主題所述。
一般而言,您會使用 Assert 將新物件放在規則引擎的工作記憶體中,並使用 Update 來更新 工作記憶體中已經存在的物件。 當您判斷提示新物件時,所有規則中的條件都會受到評估。 當您更新現有物件時,只有用到已更新事實的條件會受到重新評估,而這些條件若評估為 true,即會在議程中新增動作。
以下兩個規則為範例。 假設 ItemA 和 ItemB 物件已存在於工作記憶體中。 規則 1 會評估ItemA上的Id屬性、在ItemB上設定Id屬性,然後在變更之後重新設定ItemB。 重新組譯 ItemB 時,它會視為新的物件,引擎會重新評估在述詞或動作中使用物件 ItemB 的所有規則。 這可確保規則 2 會根據規則 1 中所設定的新值 重新評估 ItemB.Id。 規則 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。 針對特定規則,原則執行可能會持續很長的時間。 您可以藉由調整原則版本 的最大執行迴圈深度 屬性來減少計數。
您必須能夠在不建立無限迴圈的情況下重新建置物件, 而且 Update 函式會提供這項功能。 如同 reassert,Update 函式會執行已從規則動作變更之相關聯物件實例的Retract和Assert,但有兩個主要差異:
執行個體類型僅用於動作 (而非述詞) 的規則之議程上的動作,將保留在議程上。
在動作中僅使用執行個體類型的規則將不會重新評估。
因此,僅在述詞或在述詞與動作兩者中使用執行個體類型的規則將會重新評估,而其動作會適當地加入到議程。
將上述範例變更為使用 Update 函式可確保只有規則 2 會重新評估,因為 ItemB 用於規則 2 的條件中。 規則 1 不會重新評估,因為 ItemB 只會在規則 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函式一樣。
IF ItemA.Id == 1 and ItemA.Value != 20
THEN ItemA.Value = 20
Update(ItemA)
在 ItemA.Value 上新增檢查可防止第一次執行規則 1 的動作之後,再次評估為 true 。
以下兩個規則為範例。 假設: 「規則 1」會評估訂單訊息中的項目總數,而「規則 2」會在總數大於或等於 10 時,將狀態設定為「需要核准」。
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 時重新評估條件,您必須在父節點上呼叫 Update 函式, (已修改節點的 Items) (TotalCount) 。 如果您如下文所示變更「規則 1」,然後再測試一次,您應會看見 [狀態] 欄位的值設定為「需要核准」。
<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 。