skills/dotnet/patterns/unit-of-work/SKILL.md
Provide transactional boundary control for write operations in .NET Clean Architecture applications. Use when: - Implementing command handlers that require database transactions - Managing transaction boundaries across multiple repository operations - Coordinating atomic operations in Clean Architecture applications - Handling nested transactions in scoped dependency injection scenarios - Preventing repository-level transaction management anti-patterns Triggers: "transaction", "unit of work", "atomic operation", "transaction boundary", "UoW", "database transaction"
npx skillsauth add yeeehaooo/WorkSpace unit-of-workInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Provide transactional boundary control for write operations while maintaining Clean Architecture layer separation.
Applies to:
BeginAsync() / CommitAsync() / RollbackAsync()IUnitOfWork defined in Application layer, implemented in Infrastructure layerIDbSession internally (not exposed to Application)Dispose() if transaction started but not committedSaveChanges() or CommitAsync()IDbSession directlyBeginAsync()// Application Layer
public interface IUnitOfWork : IDisposable
{
Task BeginAsync(CancellationToken cancellationToken = default);
Task CommitAsync(CancellationToken cancellationToken = default);
Task RollbackAsync(CancellationToken cancellationToken = default);
}
// Infrastructure Layer
public class DapperUnitOfWork : IUnitOfWork
{
private readonly IDbSession _session;
private bool _transactionStarted = false;
public DapperUnitOfWork(IDbSession session)
{
_session = session;
}
public async Task BeginAsync(CancellationToken cancellationToken = default)
{
if (!_transactionStarted)
{
await _session.BeginTransactionAsync(cancellationToken);
_transactionStarted = true;
}
}
public async Task CommitAsync(CancellationToken cancellationToken = default)
{
if (_transactionStarted)
{
await _session.CommitTransactionAsync(cancellationToken);
_transactionStarted = false;
}
}
public async Task RollbackAsync(CancellationToken cancellationToken = default)
{
if (_transactionStarted)
{
await _session.RollbackTransactionAsync(cancellationToken);
_transactionStarted = false;
}
}
public void Dispose()
{
if (_transactionStarted)
{
_session.RollbackTransactionAsync().GetAwaiter().GetResult();
}
}
}
// Handler Usage
public class CreateOrderHandler : ICommandHandler<CreateOrderCommand>
{
private readonly IUnitOfWork _uow;
private readonly IOrderRepository _orderRepo;
private readonly IInventoryRepository _inventoryRepo;
public async Task<Result> Handle(CreateOrderCommand cmd, CancellationToken ct)
{
await _uow.BeginAsync(ct);
try
{
var order = new Order(cmd.OrderId, cmd.Items);
await _orderRepo.AddAsync(order, ct);
foreach (var item in cmd.Items)
{
await _inventoryRepo.ReserveAsync(item.ProductId, item.Quantity, ct);
}
await _uow.CommitAsync(ct);
return Result.Success();
}
catch
{
await _uow.RollbackAsync(ct);
throw;
}
}
}
This pattern works well with:
development
Create reusable .NET atomic capability code snippets that can be directly copied and pasted. Use when: - Creating single-purpose code snippets - Building reusable code templates - Implementing atomic technical capabilities - Creating copy-pasteable code blocks - Building snippet library for common patterns Triggers: "create snippet", "code snippet", "reusable snippet", "atomic snippet", "copy-paste code"
development
Create Docker Compose configuration for containerized .NET application development and deployment. Use when: - Containerizing .NET applications - Setting up local development environment with dependencies - Creating multi-container setups (API + DB + Redis) - Defining service dependencies and networking - Building docker-compose.yml for development or production Triggers: "docker compose", "containerize", "multi-container", "docker-compose.yml", "docker setup"
tools
Create adapter structure for integrating third-party APIs in Clean Architecture applications. Use when: - Integrating external APIs or services - Creating HTTP client adapters for third-party services - Implementing API integration with error handling - Setting up adapter pattern for external dependencies - Building resilient external service integrations Triggers: "api adapter", "third-party api", "external service", "http client adapter", "api integration"
development
Enterprise backend structure built on Clean Architecture, DDD, CQRS, and Vertical Slice API Design with Dapper-first persistence. Use when: - Creating new enterprise backend projects - Implementing Clean Architecture with DDD and CQRS - Building vertical slice API endpoints - Using Dapper as primary persistence mechanism - Organizing modules by UseCase-driven and Model-driven separation Triggers: "dmis structure", "clean architecture", "enterprise backend", "DDD CQRS", "vertical slice", "dapper"