更新函数

调用Update函数时,一个对象将根据新数据和状态重新插入引擎以进行重新评估。 该对象可以是 TypedXmlDocument 或 .NET 类或 DataConnectionTypedDataTable 的类型。

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

通常,使用 Assert 将新对象放置在规则引擎的工作内存中,并使用 Update 更新工作内存中的现有对象。 断言新对象时,会评估所有规则中的条件。 更新现有对象时,仅重新评估使用更新事实的条件,如果这些条件的计算结果为 true,则会将这些操作添加到议程中。

对 .NET 数据使用 Update 函数

以以下两个规则为例。 假设 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,因为 ItemB 用于规则 2 的条件。 规则 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 上调用更新时会重新评估它。 如果其他位置未更改 ItemA.Id 的值,则规则 1 将继续评估为 true,从而导致对 A 再次调用 Update 。规则设计器必须确保不会创建此类循环方案。

合适的方法会因规则的性质而有所不同。 下面是一种简单的机制,用于解决上述示例中的问题。

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

规则 1

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

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

对 XML 数据使用更新函数

以以下两个规则为例。 假设这一点。 规则 1 评估采购订单消息中项目的总计数,如果总计数大于或等于 10,则 rule2 将状态设置为“需要审批”。

规则 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 时重新计算条件,需要在修改的节点的父节点(Items)上调用 Update 函数(TotalCount)。 如果将 Rule1 更改为如下所示,然后再测试一次,您应该会看到“状态”字段的值设置为“需要审批”。

<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)  

对数据库事实使用 Update 函数

类型化数据表

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

DataConnection

不支持更新 DataConnection 。 请改用 Assert

另请参阅

引擎控制函数