+This is a wrapper around L<Rose::DB/do_transaction> that does a few additional
+things, and should always be used in favour of the other:
+
+=over 4
+
+=item Composition of transactions
+
+When C<with_transaction> is called without a running transaction, a new one is
+created. If it is called within a running transaction, it performs no
+additional handling. This means that C<with_transaction> can be safely used
+within another C<with_transaction>, whereas L<Rose::DB/do_transaction> can not.
+
+=item Return values
+
+C<with_transaction> adopts the behaviour of C<eval> in that it returns the
+result of the inner block, and C<undef> if an error occurred. This way you can
+use the same pattern you would normally use with C<eval> for
+C<with_transaction>:
+
+  SL::DB->client->with_transaction(sub {
+     # do stuff
+     # and return nominal true value
+     1;
+  }) or do {
+    # transaction error handling
+    my $error = SL::DB->client->error;
+  }
+
+or you can use it to safely calulate things.
+
+=item Error handling
+
+The original L<Rose::DB/do_transaction> gobbles up all exceptions and expects
+the caller to manually check the return value and error, and then to process
+all exceptions as strings. This is very fragile and generally a step backwards
+from proper exception handling.
+
+C<with_transaction> only gobbles up exceptions that are used to signal an
+error in the transaction, and returns undef on those. All other exceptions
+bubble out of the transaction like normal, so that it is transparent to typos,
+runtime exceptions and other generally wanted things.
+
+If you just use the snippet above, your code will catch everything related to
+the transaction aborting, but will not catch other errors that might have been
+thrown. The transaction will be rolled back in both cases.
+
+If you want to play nice in case your transaction is embedded in another
+transaction, just rethrow the error:
+
+  $db->with_transaction(sub {
+    # code deep in the engine
+    1;
+  }) or die $db->error;
+
+=back
+