Funzione UPDATE
Quando viene richiamata una funzione Update , l'oggetto viene rivalutato nel motore per la rivalutazione, in base ai nuovi dati e allo stato. L'oggetto può essere di tipo TypedXmlDocument o classe .NET o DataConnection o TypedDataTable.
È anche possibile usare la funzione Update per migliorare le prestazioni del motore e impedire scenari di ciclo infinito, come descritto in questo argomento.
In genere, si usa Assert per inserire un nuovo oggetto nella memoria di lavoro del motore delle regole e usare Update per aggiornare un oggetto già esistente nella memoria di lavoro. Quando si dichiara un nuovo oggetto, vengono valutate le condizioni di tutte le regole. Quando si aggiorna un oggetto esistente, vengono rivalutate solo le condizioni che utilizzano il fact aggiornato e all'agenda vengono aggiunte azioni se tali condizioni restituiscono true.
Si prendano come esempio le due regole riportate di seguito. Si supponga che gli oggetti ItemA e ItemB esistano già in memoria di lavoro. La regola 1 valuta la proprietà Id in ItemA, imposta la proprietà Id su ItemB e quindi riassetta ItemB dopo la modifica. Quando ItemB viene rivalutato, viene considerato come nuovo oggetto e il motore restituisce nuovamente tutte le regole che usano ItemB oggetto nei predicati o nelle azioni. Ciò garantisce che la regola 2 venga rivalutata rispetto al nuovo valore di ItemB.Id, come impostato nella regola 1. La regola 2 potrebbe non essere riuscita la prima volta che è stata valutata, ma restituisce true la seconda volta che viene valutata.
IF ItemA.Id == 1
THEN ItemB.Id = 2
Assert(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
La possibilità di dichiarare nuovamente oggetti nella memoria di lavoro consente all'utente di controllare in modo esplicito il comportamento in scenari di concatenamento dell'inoltro. Tuttavia, un effetto collaterale è che anche la regola 1 viene nuovamente valutata. Poiché ItemA.Id non è stato modificato, la regola 1 restituisce di nuovo true e l'azione Assert(ItemB) viene attivata nuovamente. Il risultato è che la regola crea una situazione di ciclo infinito.
Nota
Il numero massimo massimo predefinito di rivalutazione delle regole è 2^32. Per determinate regole, l'esecuzione dei criteri potrebbe durare per molto tempo. È possibile ridurre il conteggio modificando la proprietà Maximum Execution Loop Depth della versione dei criteri.
È necessario riassettare gli oggetti senza creare cicli infiniti e la funzione Update offre questa funzionalità. Analogamente a una riassettazione, la funzione Update esegue Il ritiro e l'asserzione delle istanze dell'oggetto associato, che sono state modificate dalle azioni delle regole, ma esistono due differenze principali:
Le azioni nell'agenda per le regole in cui il tipo di istanza viene utilizzato solo nelle azioni (non nei predicati) rimangono nell'agenda.
Le regole che utilizzano solo il tipo di istanza nelle azioni non vengono valutate nuovamente.
Pertanto, le regole che utilizzano i tipi di istanza solo nei predicati o sia nei predicati che nelle azioni vengono valutate nuovamente e le relative azioni vengono aggiunte all'agenda.
La modifica dell'esempio precedente per l'uso della funzione Update garantisce che solo la regola 2 venga rivalutata perché ItemB viene usata nella condizione della regola 2. La regola 1 non viene rivalutata perché ItemB viene usato solo nelle azioni della regola 1, eliminando lo scenario di ciclo.
IF ItemA.Id == 1
THEN ItemB.Id = 2
Update(ItemB)
IF ItemB.Id == 2
THEN ItemB.Value = 100
È comunque possibile che si creino scenari di ciclo. Si consideri, ad esempio, la seguente regola:
IF ItemA.Id == 1
THEN ItemA.Value = 20
Update(ItemA)
Poiché ItemA viene usato nel predicato, viene rivalutato quando viene chiamato Update in ItemA. Se il valore di ItemA.Id non viene modificato altrove, la regola 1 continua a valutare true, causando la chiamata nuovamente dell'aggiornamento in A. La finestra di progettazione regole deve assicurarsi che gli scenari di ciclo come questo non vengano creati.
L'approccio corretto varia a seconda della natura delle regole. Di seguito è descritto un semplice meccanismo che consente di risolvere il problema dell'esempio precedente.
La funzione Update può essere usata in Business Rule Composer con un riferimento alla classe, come con le funzioni Assert, Retract o RetractByType.
IF ItemA.Id == 1 and ItemA.Value != 20
THEN ItemA.Value = 20
Update(ItemA)
L'aggiunta del controllo in ItemA.Value impedisce alla regola 1 di valutare nuovamente true dopo l'esecuzione delle azioni della regola 1.
Si prendano come esempio le due regole riportate di seguito. Si supponga che la regola 1 restituisca il numero totale degli elementi di un messaggio di ordine di acquisto e che la regola 2 imposti lo stato su "Needs approval" se il numero totale è maggiore o uguale 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"
Se si passa il seguente messaggio di ordine di acquisto (PO) come input a questo criterio, si noti che lo stato non è impostato su "Richiede approvazione" anche se il numero totale di elementi è 14. Poiché la regola2 viene valutata solo all'inizio quando il valore del campo TotalCount è 0 e la regola non viene valutata ogni volta che il numero totale disponibile viene aggiornato. Per avere rivalutato le condizioni ogni volta che totalCount viene aggiornato, è necessario chiamare la funzione Update nel nodo padre (Items) del nodo modificato (TotalCount). Se si modifica la regola 1 come mostrato di seguito e si esegue un altro test, il valore del campo Status dovrebbe essere impostato su "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>
La regola 1 modificata è la seguente:
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)
Se l'aggiornamento viene chiamato in un oggetto TypedDataTable, l'aggiornamento viene chiamato dal motore in tutti i TipidDataRows associati. L'aggiornamento può essere chiamato anche in singoli TipidDataRows.
L'aggiornamento di un oggetto DataConnection non è supportato. Usare invece Assert .