transaction<T> method Null safety

Future<T?> transaction<T>(
  1. Future<T?> transactionBlock(
    1. ManagedContext transaction
    )
)

Runs all Querys in transactionBlock within a database transaction.

Queries executed within transactionBlock will be executed as a database transaction. A transactionBlock is passed a ManagedContext that must be the target of all queries within the block. The context passed to the transactionBlock is not the same as the context the transaction was created from.

You must not use the context this method was invoked on inside the transactionBlock. Doing so will deadlock your application.

If an exception is encountered in transactionBlock, any query that has already been executed will be rolled back and this method will rethrow the exception.

You may manually rollback a query by throwing a Rollback object. This will exit the transactionBlock, roll back any changes made in the transaction, but this method will not throw.

TODO: the following statement is not true. Rollback takes a string but the transaction returns . It would seem to be a better idea to still throw the manual Rollback so the user has a consistent method of handling the rollback. We could add a property to the Rollback class 'manual' which would be used to indicate a manual rollback. For the moment I've changed the return type to Future as The parameter passed to Rollback's constructor will be returned from this method so that the caller can determine why the transaction was rolled back.

Example usage:

    await context.transaction((transaction) async {
       final q = new Query<Model>(transaction)
        ..values = someObject;
       await q.insert();
       ...
    });

Implementation

Future<T?> transaction<T>(
  Future<T?> Function(ManagedContext transaction) transactionBlock,
) {
  return persistentStore.transaction(
    ManagedContext.childOf(this),
    transactionBlock,
  );
}