Starcounter
HomeDownloadDocsCommunity
2.3.1
2.3.1
  • Starcounter Documentation
  • Getting Started
  • Starcounter
    • Collapsing the Stack
      • Complexity and Scalability Tradeoff
      • The Future of Micro-Services
      • 10 Benefits of Collapsing the Stack
    • Integrated Database and Web Server
  • Hello World - Tutorial
    • Create a Database Class
    • Create a Real Time UI
    • First Interactive UI
    • Computed Properties
    • Expense Tracker
    • Cancel and Delete
    • The Next Step
  • Guides
    • Database
      • Database Classes
      • Data manipulation
      • Object Identity and Object References
      • Querying with SQL
      • Data Types
      • Relations
      • Inheritance
      • Sharing data
      • Database Configuration
      • Comparing Database Objects
      • Referential Integrity and Constraints
    • SQL
      • Identifiers
      • Path Expressions
      • Data operators
      • Joins
      • Aggregates
      • Comparisons and Logical Operators
      • Sorting
      • Fetch
      • Offset Key
      • Indexes
      • Literals
      • Query Plan Hints
      • Reserved words
      • Query for Database Classes
      • SQL Isolation Between Applications
    • Transactions
      • Short-Running Transactions
      • Long running transactions
      • Using Transactions
      • Running Background Jobs
      • Commit Hooks
    • Typed JSON
      • JSON-by-example
      • Code-Behind
      • Data Bindings
      • Callback Methods
      • Responding with JSON
      • Accepting JSON in Requests
      • Primitive Arrays and Single Value Types
      • Typed JSON Internals
    • Blendable Web Apps
      • Starcounter MVVM
      • Palindrom
      • Client-Side Stack
      • Sessions
      • HTML Views
      • App Shell
      • Web Components
      • View Attaching
      • View Composing
      • HTML Compositions
      • HTML Views Blending Guidelines
      • Avoiding CSS conflicts
      • Debugging
    • Network
      • HTTP
      • Internal Self Calls
      • Middleware
      • Anonymous or Substitute Handlers
      • URL Aliases and Redirects
      • Network Gateway
      • Static File Server
      • External HTTP Calls
      • WebSocket
      • Avoiding URI conflicts
      • TCP Sockets
      • UDP Sockets
    • Publishing Apps
    • Working with Starcounter
      • Release Channels
      • Starting and Stopping Apps
      • Administrator Web UI
      • Star CLI
      • StarAdmin CLI
      • StarDump CLI
      • Working in Visual Studio
      • Error Log
      • Using HTTPS on NGINX
      • Using HTTPS on IIS
      • Run Starcounter in Production
      • Weaver
      • Investigating App Crashes
      • Configuration Structure
      • Database Refactoring
      • Using Unload/Reload to Modify Database Schema
      • Kernel Questions and Answers
      • Log Files
  • Cookbook
    • Attach an HTTP Request to an Existing Long-Running Transaction
    • Cookie-Based Authentication
    • Timestamp on Object Creation
    • Creating Strongly Typed JSON Collections
    • Migrating From 2.2 to 2.3+
    • Multiple Pages
    • Icons
    • Proposed Project Structure
    • Acceptance Testing with Selenium
    • Requesting a User to Authenticate
    • How to delete unused tables and columns
Powered by GitBook
On this page
  • Introduction
  • Choosing Transaction
  • Side Effects
  • Rollbacks
  • Conflics
  • Mixing Transactions
  • Long-Running in Long-Running
  • Short-Running in Long-Running
  • Long-Running in Short-Running
  • Short-Running in Short-Running
  • ScErrReadOnlyTransaction
  1. Guides
  2. Transactions

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:

[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:

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):

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:

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

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))

For example:

[Database]
public class Person {}

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

To fix this, wrap the operation in a transaction:

[Database]
public class Person {}

class Program
{
    static void Main()
    {
        Db.Transact(() => new Person());
    }
}
PreviousLong running transactionsNextRunning Background Jobs

Last updated 7 years ago