100, and you update it to
110in a transaction. At the same time, another transaction is also reading the value of the cell as
100and updates it to
120. What should the end result be?
ITransactor.TryTransactmethod to retry when there is a conflict.
ITransactor.Transactis 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
ITransactor.Transactmethod is a delegate containing the code to run within the transaction. We can get the
ITransactorinstance from the application service provider:
ITransactorto create new database transactions.
ITransactor.Transactis 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, it's better to use
Taskthat completes when the transaction commits or rolls back, which lets you avoid thread blocking.
ITransactor.TransactAsyncis the asynchronous counterpart of
ITransactor.Transact. It gives the developer more control of balance throughput and latency. The function returns a
Taskthat is marked as completed and successful with the property
IsCompletedSuccessfullywhen the database operations are written to the transaction log which persists the changes.
ITransactor.TransactAsyncare syntactically identical, but semantically different since
ITransactor.TransactAsyncis used with
await. While awaiting the transaction log write operation, it's possible to do other things:
ITransactor.Transact, but it comes with certain risks. For example, if there's a power outage or other hardware failure after the email is sent but before writing to the log, the email will be incorrect. Even if the user got a confirmation, the order will not be in the database since it was never written to the transaction log.
ITransactor.TransactAsyncis also useful when creating many transactions in sequence:
ITransactor.TransactAsyncshould execute in as short time as possible, since conflicts are more likely to occur the longer the transaction is. And retrying long transactions due to conflicts can be expensive resource-wise. Therefore it's best practice to break big transactions into smaller ones.