> For the complete documentation index, see [llms.txt](https://tldocs.gitbook.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tldocs.gitbook.io/documentation/framework/window-handling-object/transactions.md).

# 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
```

{% hint style="warning" %}
Notice that one response Module could have TransactionCreate set on true, because while opening a module using OpenResponseModule with Transaction as parameter, it will automatically set TransactionCreate on false and will pass the Transaction of the parent.
{% endhint %}

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

{% hint style="success" %}
Best practice: The BusinessObjects should **not** return negative values for errors. Instead, exceptions, containing all the details about the error, should be thrown.
{% endhint %}

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…

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

The Method inside the WHO should look like this:

```csharp
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.");     
    }
}
```

{% hint style="info" %}
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.
{% endhint %}

```csharp
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;
}
```

{% hint style="info" %}
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.
{% endhint %}

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

Example:

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

Using current object transaction to do other sql operations

```csharp
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();
}
```

{% hint style="warning" %}
Note:  CurrentTransaction is obsolete, Transaction is the new name of the transaction property
{% endhint %}
