Db.TryTransact
method to retry when there is a conflict.Db.Transact
Db.Transact
is the simplest way to create a transaction in Starcounter. It declares a transactional scope and runs synchronously, as described above. The argument passed to the Db.Transact method is a delegate containing the code to run within the transaction. In code, it looks like this:Db.Transact
is synchronous, it blocks the executing thread until the transaction completes. Thus, if the transaction takes more than a few milliseconds to run, it might prevent your application's performance from scaling with CPU core counts. In those cases, use Db.TransactAsync
instead. Db.TransactAsync
returns a Task
that completes when the transaction commits or rolls back which lets you avoid blocking.Db.TransactAsync
Db.TransactAsync
is the asynchronous counterpart of Db.Transact
. It gives the developer more control to balance throughput and latency. The function returns a Task
that is marked as completed and successful with the property IsCompletedSuccessfully
when the database operations are written to the transaction log which persists the changes.Db.Transact
and Db.TransactAsync
are syntactically identical, but semantically different since Db.TransactAsync
is used with await
:Db.TransactAsync
is useful when creating many transactions in sequence:SendInvoice
transaction, you'd expect that the invoice has been committed to the database. That is not the case. To preserve the atomicity of the outer transaction, the changes have to be committed at the same time at the end of the outer transaction's scope. Thus, if the invoice was sent on line 14 and then the whole transaction could roll back in RemoveFromInventory
and undo AddInvoiceToDb
. This would cause the customer to receive an invoice that is not stored in the database.SendInvoice
:AddInvoiceToDb
are committed and you can be sure that the invoice would be sent first when the invoice is safely in the database. In this case, it would be when the outer transaction scope terminates. If there was no outer transaction, the invoice would be sent when the transaction with AddInvoiceToDb
terminates. Thus, onCommit
ensures that the calls are made in the correct order no matter what.onCommit
delegate:onCommit
delegate, you acknowledge that the changes are not guaranteed to commit after the transaction scope.ArgumentNullException
.Db.Transact
and Db.TransactAsync
should execute in as short time as possible because conflicts are more likely the longer the transaction is. Conflicts requires long transactions to run more times which can be expensive. The solution is to break big transactions into smaller ones.ScErrNoTransactionAttached
:async
/await
in transactions. To perform database operations asynchronously in transactions, you have to make sure it uses the enclosing context: