# Using Transactions

## Introduction

Although short- and long-running transaction are similar in many ways, there are also some crucial differences. This page outlines how to choose what transaction to use and how to mix transactions.

## Choosing Transaction

It's important to chose the right transaction. In most situation, the choice is clear - if you are going to attach a transaction to a view-model, use a long-running transaction, otherwise, use a short-running transaction. When the choice is not clear, consider these factors:

### Side Effects

Since `Db.Transact` and `Db.TransactAsync` can run more than once because of conflicts, they should not have any side effects, such as HTTP calls or writes to a file. \`Db.Scope\` can have side effects, as long as it's not in an iterator.

### Rollbacks

The only way to rollback changes in `Db.Transact` and `Db.TransactAsync` is to throw an exception in the transaction. The alternative is to use `Db.Scope` with `Transaction.Rollback`.

### Conflics

If conflicts are likely, use `Db.Transact` or `Db.TransactAsync` because these handle conflicts while `Db.Scope` doesn't.

## Mixing Transactions

Transactions can be mixed as outer and inner transactions - one transaction wraps around the other. These are the possible combinations and their effects:

| Outer | Inner | Effect                                  |
| ----- | ----- | --------------------------------------- |
| Long  | Long  | Execute inner as part of outer          |
| Long  | Short | Execute inner as a separate transaction |
| Short | Long  | Not supported. Run-time error           |
| Short | Short | Execute inner as part of outer          |

Transactions can be mixed as outer and inner transactions - one transaction wraps around the other. These are the possible combinations and their effects:

### Long-Running in Long-Running

With a long-running transaction inside a long-running transaction, they act as if they were one transaction:

```csharp
[Database]
public class Person {}

[Database]
public class Animal {}

class Program
{
    static void Main()
    {
        Db.Scope(() =>
        {
            new Person();

            Db.Scope(() =>
            {
                Transaction.Current.Commit(); // Commits the Person
                new Animal();
            });

            Transaction.Current.Commit(); // Commits the Animal
        });
    }
}
```

### Short-Running in Long-Running

Short-running transactions in long-running transactions are executed separately:&#x20;

```csharp
using Starcounter;
using System.Linq;

[Database]
public class Person {}

[Database]
public class Animal
{
    public string Specie { get; set; }
}

class Program
{
    static void Main()
    {
        Db.Scope(() =>
        {
            new Person();

            Db.Transact(() =>
            {
                new Animal() { Specie = "Dog" };
            }); // Animal is commited to the database - transaction is done

            // The Animal committed can be accessed in the outer transaction
            var animal = Db.SQL("SELECT a FROM Animal a").First();

            // Rolls back the Person but not the Animal
            Transaction.Current.Rollback();
        });
    }
}
```

### Long-Running in Short-Running

Using long-running transactions in short-running transactions is not supported, it will throw `ScErrTransactionLockedOnThread (SCERR4031)`:

```csharp
Db.Transact(() =>
{
    Db.Scope(() => // SCERR4031
    {
        new Person(); 
    });
}); 
```

### Short-Running in Short-Running

Short-running in short-running transactions work the same as with long-running in long-running transactions: the inner transaction is executed as a part of the outer:

```csharp
using Starcounter;

[Database]
public class Person {}

[Database]
public class Animal {}

class Program
{
    static void Main()
    {
        Db.Transact(() =>
        {
            Db.Transact(() =>
            {
                new Person();
            }); // Person is not commited

            new Animal();
        }); // Animal and Person are commited
    }
}
```

## ScErrReadOnlyTransaction

&#x20;If an operation is done on the database without a transaction an exception will be thrown:

```
The transaction is readonly and cannot be changed to write-mode. (ScErrReadOnlyTransaction (SCERR4093))
```

&#x20;For example:

```csharp
[Database]
public class Person {}

class Program
{
    static void Main()
    {
        new Person(); // SCERR4093
    }
}
```

&#x20;To fix this, wrap the operation in a transaction:

```csharp
[Database]
public class Person {}

class Program
{
    static void Main()
    {
        Db.Transact(() => new Person());
    }
}
```
