I've been implementing some of the patterns from Chapter 7, including the Unit of Work + repository for Dapper (and SQL db persistence), and I encountered an issue around performance.
The use of TransactionScope in the UoW, while very simple and elegant, seems to cause a huge performance overhead. In an integration test project where I add an aggregate with 1000 child objects, using TransactionScope makes the test execution time increase about ten-fold. In order to overcome this, I added some additional code to the UnitOfWork and Repository classes to allow the UnitOfWork to open the connection and begin the transaction on the first of the repositories registered with it - this transaction is then passed into each of the peristence methods so that they can make use of it.
This makes the UoWRepo interface looks like so:
public interface IUnitOfWorkRepository
Task PersistCreationOf(IAggregate aggregate, IDbTransaction tran);
Task PersistUpdateOf(IAggregate aggregate, IDbTransaction tran);
And in the repo implementation:
public async Task<IDbTransaction> BeginTransaction()
var connection = GetConnection();
And finally, in the UoW Commit method:
//Having kept tabs on the first repo registered, now begin tran
var tran = await _initialRepository.BeginTransaction();
var connection = tran.Connection;
foreach (var entity in _addedEntities.Keys)
await _addedEntities[entity].PersistCreationOf(entity, tran);
foreach (var entity in _changedEntities.Keys)
await _changedEntities[entity].PersistUpdateOf(entity, tran);
The persistence methods then simply make use of the tran, and execute against the connection associated with the tran. This works, and I see vastly improved performance.
However, I wanted to know whether anyone else had encountered any performance issues with TransactionScope (I had anticipated *some* overhead, but not this much), and whether I am guilty of any error in the above approach. I am not concerned about distributed/escalated transactions, etc. so don't actually need a lot of the added value of TransactionScope.