Transactions

xTransaction in WHO with passing down to all BusObjects (BusinessObjects). The WHO should have the responsability for commit/rollback. Each BusinessObject should issue an exception in case of an error and this exception should be caught by the WHO. This will allow multi-level BusinessObjects working together without suppressing the real exception on an intermediary level (by a “parent” BusinessObject).

Each WHO has a property called “TransactionCreate” (preset on TRUE) which:

  • creates a transaction-object (called “Transaction”) when a module is opened and applies it to its BusinessObject

  • the Save method from the base class automatically commits the transaction

  • when the module is closed that transaction calls the dispose method

“TransactionCreate” will be set on FALSE (in the constructor) if the module:

  • does not work with the database

  • is an internal module (xModule)

  • is response module and receives the transaction from the parent context

  • does not require transactions for any other reason

Each action done in the WHO needs to commit its changes. The handling of the exception is done in the WHO.

Example: Steps to implement for proper transaction management:

In the constructor of the WHO specify that a transaction is needed. This is all that has to be done. This transaction is passed on to the BusObj, which then gives it to its children, and so on…

public wndPers() : base("busPers")
{
    TransactionCreate = true;
}

The Method inside the WHO should look like this:

public virtual void GeneratePers(dsBPartnerCustom.PersRow row)
{
    //     ......
    // GP generieren
    try
    {
        int retVal = BusObj.GenerateBPContact(lrTree.LRTree, row, true);
        Transaction.Commit();
    }
    catch (Exception ex)
    {
        Transaction.Rollback();
        xMessageBox.ShowException(ex, "Fehler beim Erstellen des Geschäftspartners.");     
    }
}

retVal is used to know the result of the action (if all went well), but not for Errors. All errors happening inside GenerateBP pop out as exceptions. Also important here is that first the transaction is rolled back, THEN the message is shown. This way, the user can “study” the message without eventually locking some Database-Rows.

public virtual void GenerateBPContact (LrTree tree, dsBPartnerCustom.PersTelRow row, bool genSubPers = true)
{
		// Inits		
		// ...
		// UnterBP
		
		if (genSubPers)
		{
				foreach (var child in children)
				{
						GenerateBP (tree, child.Info.DataRow, true);
						int unterBP = child.Info.DataRow["nr"].ToInt(0);
				}
		}

    //...
    
    return 1;
}

Notice that GenerateBP(...) is a recursive function and only if ALL BP are created correctly, the WHO-Method will Commit the transaction. If an error occurs, everything is rolled back.

To create a busObj inside a busObj, use the Function „CreateChildBusinessObject”. This way, the transaction is passed on to this new Object.

Example:

var pers = this.CreateChildBusinessObject<busPers>();

Using current object transaction to do other sql operations

try
{
    Sql.Execute(Transaction, "DELETE FROM gebinde WHERE bel_typ = {0} AND bel_nr = {1} AND typ = 10", belTyp, belNr);
}
catch (Exception)
{
    if (Transaction != null)
    {
        Rollback();
    }

    throw;
}

int result = Save();
if (result < 0 && Transaction != null)
{
    Rollback();
}

Last updated