ComponentOne DataObjects for .NET
Action Order and Execution Mode
DataObjects for .NET (Enterprise Edition) > Business Logic > Action Order and Execution Mode

When handling an event in business logic code, you can perform an action that triggers another business logic event, that in turn is handled and triggers yet another event, and so on. For example, handling a field change event, you can set another field, or perform any other possible action. In most data frameworks, such actions are either blocked or can only be handled in a straightforward way creating uncontrolled recursion. Uncontrolled event triggering leads to complicated situations often creating unintended effects and side effects. Every database developer can recall situations where a harmless code intended to, say, commit a record once certain fields are entered by the end user, either does not work or produces unexpected and often disastrous results.

DataObjects for .NET solves this problem by allowing the developer to exercise full control over the order of actions performed by business logic code. Various actions, including method calls and field value assignments, can be specified to take place either immediately or after DataObjects for .NET has completed performing previous actions that are already in the queue, and completed handling the events that are being handled.

When the end user initiates an action leading to a business logic event (for example, sets a field value, or deletes a row), DataObjects for .NET starts executing it by creating an action context stack. The initial state of this stack is one level with the requested action contained in it. If no actions have been requested by the business logic code while this action was handled, the stack is destroyed. If, however, an action (that itself can trigger a business logic event), is requested while handling this action, the requested action can be processed by DataObjects for .NET in two different ways:

To control the action order, use the ExecutionMode property. Its two possible values, Immediate (default) and Deferred, specify the two modes described above.

ExecutionMode is a read-only property. You never need to set execution mode permanently. You only need to set it for the duration of a certain fragment of code, after which it must be restored to its previous value. Since changing execution mode can inadvertently break your code, we strongly recommend using try-finally blocks to ensure that previous execution mode is always restored.

To set execution mode, call the PushExecutionMode method, passing it the new mode as a parameter. To restore the previous execution mode, call PopExecutionMode.

For example, the following code (taken from Adding Rows and Primary Keys) sets the primary key field in a newly added row immediately after the row has been created.

To write code in Visual Basic

VB
Copy Code
Private Sub table_Customers_AfterAddNew(ByVal sender As Object, ByVal e As C1.Data.RowChangeEventArgs) Handles TableLogic1.AfterAddNew
    e.DataTable.DataSet.PushExecutionMode _
         (C1.Data.ExecutionModeEnum.Deferred)
    'The following field value assignment and a method call
    'will actually execute only after all other actions handling
    'the row addition will be finished
    e.Row("CustomerID") = TextBox1.Text
    e.Row.EndEdit()
    e.DataTable.DataSet.PopExecutionMode()
End Sub

To write code in C#

C#
Copy Code
private void table_Customers_AfterAddNew(object sender, C1.Data.RowChangeEventArgs e)
{
    e.DataTable.DataSet.PushExecutionMode(ExecutionModeEnum.Deferred);
    // The following field value assignment and a method call
    // will actually execute only after all other actions handling
    // the row addition will be finished
    e.Row["CustomerID"] = textBox1.Text;
    e.Row.EndEdit();
    e.DataTable.DataSet.PopExecutionMode();
}

Although this code would probably work without changing execution mode, doing so would be unsafe, since it would trigger EndEdit before AddNew is completely finished (for example, a grid or another bound control could be not yet notified at that time that a row has been added).

What we really want in cases like this ("after this, do that") is to emulate end user actions, as if the end user typed the key value after adding a new row, which is essentially what DataObjects for .NET is doing in the Deferred execution mode.