Función Update
Cuando se invoca una función Update , el objeto se vuelve a evaluar en el motor, en función de los nuevos datos y el estado. El objeto puede ser de tipo TypedXmlDocument o .NET clase o DataConnection o TypedDataTable.
También puede usar la función Update para mejorar el rendimiento del motor y evitar escenarios de bucle sin fin, como se describe en este tema.
Normalmente, se usa Assert para colocar un nuevo objeto en la memoria de trabajo del motor de reglas y usar Update para actualizar un objeto ya existente en la memoria de trabajo. Cuando se impone un objeto nuevo, se evalúan las condiciones de todas las reglas. Cuando se actualiza un objeto existente, solo se vuelven a evaluar las condiciones que usan el hecho actualizado, y las acciones se agregan a la agenda si estas condiciones se evalúan como true.
Supongamos las dos reglas siguientes como ejemplo. Supongamos que los objetos ItemA y ItemB ya existen en memoria de trabajo. La regla 1 evalúa la propiedad Id en ItemA, establece la propiedad Id en ItemB y, a continuación, vuelve a establecer ItemB después del cambio. Cuando ItemB se vuelve a restablecer, se trata como un nuevo objeto y el motor vuelve a evaluar todas las reglas que usan el objeto ItemB en los predicados o acciones. Esto garantiza que la regla 2 se vuelva a evaluar con el nuevo valor de ItemB.Id, tal como se establece en la regla 1. La regla 2 puede haber producido un error la primera vez que se evaluó, pero se evalúa como true la segunda vez que se evalúa.
IF ItemA.Id == 1
THEN ItemB.Id = 2
Assert(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
Esta capacidad de volver a imponer objetos en la memoria de trabajo permite al usuario tener un control explícito sobre el comportamiento en los escenarios de encadenamiento directo. Sin embargo, un efecto secundario de esta reimposición en este ejemplo es que la Regla 1 también se vuelve a evaluar. Dado que no se cambió ItemA.Id, la regla 1 vuelve a evaluarse como true y la acción Assert(ItemB) se activa de nuevo. En consecuencia, la regla crea una situación de bucle infinito.
Nota
El número máximo de bucles predeterminado de reevaluación de reglas es 2^32. Para determinadas reglas, la ejecución de la directiva podría durar mucho tiempo. Puede reducir el recuento ajustando la propiedad Maximum Execution Loop Depth (Profundidad máxima del bucle de ejecución ) de la versión de la directiva.
Debe poder restablecer objetos sin crear bucles infinitos y la función Update proporciona esta funcionalidad. Al igual que una reserción, la función Update realiza Retract y Assert de las instancias de objeto asociadas, que se han cambiado de acciones de regla, pero hay dos diferencias clave:
Las acciones de la agenda para las reglas en las que el tipo de instancia solo se utiliza en las acciones (no en los predicados) permanecerán en la agenda.
Las reglas que solo utilizan el tipo de instancia en las acciones no se volverán a evaluar.
Por lo tanto, las reglas que utilizan los tipos de instancia solo en los predicados, o tanto en los predicados como en la acciones, se volverán a evaluar y sus acciones se agregarán a la agenda según corresponda.
Cambiar el ejemplo anterior para usar la función Update garantiza que solo se vuelva a evaluar la regla 2 porque ItemB se usa en la condición de la regla 2. La regla 1 no se vuelve a evaluar porque ItemB solo se usa en las acciones de la regla 1, lo que elimina el escenario de bucle.
IF ItemA.Id == 1
THEN ItemB.Id = 2
Update(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
No obstante, todavía es posible crear escenarios de bucle. Por ejemplo, considere la siguiente regla.
IF ItemA.Id == 1
THEN ItemA.Value = 20
Update(ItemA)
Dado que ItemA se usa en el predicado, se vuelve a evaluar cuando se llama a Update en ItemA. Si el valor de ItemA.Id no se cambia en otro lugar, la regla 1 continúa evaluando como true, lo que hace que se vuelva a llamar a Update en A. El diseñador de reglas debe asegurarse de que no se creen escenarios de bucle como este.
El enfoque adecuado para esto será distinto en función de la naturaleza de las reglas. A continuación, se muestra un mecanismo sencillo para solucionar el problema del ejemplo anterior.
La función Update se puede usar en business Rule Composer con una referencia a la clase , como con las funciones Assert, Retract o RetractByType .
IF ItemA.Id == 1 and ItemA.Value != 20
THEN ItemA.Value = 20
Update(ItemA)
Agregar la comprobación en ItemA.Value impide que la regla 1 se evalúe como true de nuevo después de que las acciones de la regla 1 se ejecuten por primera vez.
Supongamos las dos reglas siguientes como ejemplo. Suponga que. La Regla 1 evalúa el número total de elementos de un mensaje de pedido y la Regla 2 establece el estado en "Pendiente de aprobación" si el número total es mayor que o igual a 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"
Si pasa el siguiente mensaje de pedido de compra (PO) como entrada a esta directiva, observe que el estado no está establecido en "Necesita aprobación", aunque el recuento total de artículos sea 14. Se debe a que la regla2 solo se evalúa al principio cuando el valor del campo TotalCount es 0 y la regla no se evalúa cada vez que se actualiza el recuento total disponible. Para que las condiciones se vuelvan a evaluar cada vez que se actualice TotalCount , debe llamar a la función Update en el nodo primario (Elementos) del nodo modificado (TotalCount). Si cambia la Regla según se muestra abajo, y la prueba otra vez, debe ver el valor del campo Estado establecido en "Pendiente de aprobación".
<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>
La regla 1 modificada es la siguiente:
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)
Si se llama a Update en un TypedDataTable, el motor llama a Update en todos los TypedDataRows asociados. También se puede llamar a la actualización en typedDataRows individual.
No se admite la actualización de dataConnection . Use Assert en su lugar.