Update 函数

调用 Update 函数时,该对象将重新声明为引擎,以便根据新数据和状态重新计算该对象。 对象可以是 TypedXmlDocument 类型、.NET 类、 DataConnectionTypedDataTable

还可以使用 Update 函数提高引擎性能并防止本主题中所述的无限循环方案。

通常,使用 Assert 将新对象置于规则引擎的工作内存中,并使用 Update 更新工作内存中已有的对象。 当您添加新的对象时,会评估所有规则的条件。 当您更新现有对象时,仅重新评估使用已更新事实的条件,并且如果这些条件评估结果为真,则会将操作添加到议程中。

对 .NET 事实使用更新功能

现以下面两个规则举例说明。 假设对象 ItemAItemB 已存在于工作内存中。 规则 1 评估 ItemA 上的 Id 属性,在 ItemB 上设置 Id 属性,然后在更改后重新验证 ItemB。 重新确认 ItemB 时,它将被视为新对象,引擎会重新评估在谓词或操作中使用对象 ItemB 的所有规则。 这可确保根据规则 1 中设置的新值 ItemB.Id 重新计算规则 2。 规则 2 可能在第一次评估时失败,但在第二次评估规则时计算结果为 true

规则 1

IF ItemA.Id == 1  
THEN ItemB.Id = 2  
Assert(ItemB)  

规则 2

IF ItemB.Id == 2  
THEN ItemB.Value = 100  

通过将对象重新添加到工作内存的功能,用户可以显式控制正向链接方案中的行为。 而此示例中重新添加对象的副作用是还需要重新评估规则 1。 由于 ItemA.Id 未更改,规则 1 再次计算结果为 true ,并且 Assert (ItemB) 操作再次触发。 而这会导致规则产生无穷循环。

注意

重新计算规则的默认最大循环计数为 2^32。 对于某些规则,策略执行可能会持续很长时间。 可以通过调整策略版本的 “最大执行循环深度 ”属性来减少计数。

你需要能够在不创建无限循环的情况下重新生成对象,并且 Update 函数提供此功能。 与 reassert 一样, Update 函数对已从规则操作更改的关联对象实例执行 RetractAssert ,但有两个主要区别:

  • 对于只在操作中(而不在谓词中)使用实例类型的规则,其议程的操作将保留在议程中。

  • 只在操作中使用实例类型的规则将不会重新进行评估。

    因此,只在谓词中或者既在谓词中也在操作中使用实例类型的规则将会重新进行评估,并且它们的操作也将根据需要添加到议程中。

    将前面的示例更改为使用 Update 函数可确保仅重新计算规则 2,因为在规则 2 的条件中使用 ItemB 。 不会重新计算规则 1,因为 ItemB 仅在规则 1 的操作中使用,从而消除了循环方案。

规则 1

IF ItemA.Id == 1  
THEN ItemB.Id = 2  
Update(ItemB)  

规则 2

IF ItemB.Id == 2  
THEN ItemB.Value = 100  

但是,它仍然可能会创建循环。 例如,考虑以下规则:

规则 1

IF ItemA.Id == 1  
THEN ItemA.Value = 20  
Update(ItemA)  

由于谓词中使用 ItemA,因此在 ItemA 上调用 Update 时会重新计算它。 如果在其他位置未更改 ItemA.Id 的值,则规则 1 将继续计算为 true,从而导致再次在 A 上调用 Update 。规则设计器必须确保不会创建此类循环方案。

根据规则性质的不同,实现方法也会不同。 下面是解决上述示例中的问题的简单机制。

AssertRetractRetractByType 函数一样,可以在业务规则编辑器中使用对 类的引用的 Update 函数。

规则 1

IF ItemA.Id == 1 and ItemA.Value != 20  
THEN ItemA.Value = 20  
Update(ItemA)  

ItemA.Value 上添加检查可防止规则 1 在首次执行规则 1 的操作后再次计算为 true

对 XML 事实使用更新功能

现以下面两个规则举例说明。 假定 规则 1 评估采购订单消息中项目的总数,如果总数大于或等于 10,规则 2 便将状态设置为“需要批准”。

规则 1

IF 1 == 1  
THEN ProcessPO.Order:/Order/Items/TotalCount = (ProcessPO.Order:/Order/Items/TotalCount + ProcessPO:/Order/Items/Item/Count)  

规则 2

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 如下所示:

规则 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

如果对 TypedDataTable 调用 Update,则引擎将在所有关联的 TypedDataRows 上调用 Update。 还可以对单个 TypedDataRows 调用更新

DataConnection

不支持更新 DataConnection 。 请改用 断言

另请参阅

引擎控制函数