Cortex.Mediator.Behaviors.Transactional
3.1.2
dotnet add package Cortex.Mediator.Behaviors.Transactional --version 3.1.2
NuGet\Install-Package Cortex.Mediator.Behaviors.Transactional -Version 3.1.2
<PackageReference Include="Cortex.Mediator.Behaviors.Transactional" Version="3.1.2" />
<PackageVersion Include="Cortex.Mediator.Behaviors.Transactional" Version="3.1.2" />
<PackageReference Include="Cortex.Mediator.Behaviors.Transactional" />
paket add Cortex.Mediator.Behaviors.Transactional --version 3.1.2
#r "nuget: Cortex.Mediator.Behaviors.Transactional, 3.1.2"
#:package Cortex.Mediator.Behaviors.Transactional@3.1.2
#addin nuget:?package=Cortex.Mediator.Behaviors.Transactional&version=3.1.2
#tool nuget:?package=Cortex.Mediator.Behaviors.Transactional&version=3.1.2
Cortex.Mediator.Behaviors.Transactional ??
Cortex.Mediator.Behaviors.Transactional provides transactional pipeline behaviors for Cortex.Mediator, enabling automatic transaction management for command execution with commit on success and rollback on failure.
Built as part of the Cortex Data Framework, this library ensures data consistency by wrapping command handlers in transactions.
- ? Automatic Transaction Management
- ? Async/Await Support with TransactionScope
- ? Custom Transaction Contexts (EF Core, Dapper, etc.)
- ? Configurable Isolation Levels & Timeouts
- ? Selective Command Exclusion
?? Getting Started
Install via NuGet
dotnet add package Cortex.Mediator.Behaviors.Transactional
??? Setup
In Program.cs or Startup.cs:
using Cortex.Mediator.DependencyInjection;
using Cortex.Mediator.Behaviors.Transactional.DependencyInjection;
// Add mediator with transactional behaviors
builder.Services.AddCortexMediator(
new[] { typeof(Program) },
options => options.AddTransactionalBehaviors()
);
// Register transactional options (with defaults)
builder.Services.AddTransactionalBehavior();
With Custom Options
builder.Services.AddTransactionalBehavior(options =>
{
options.IsolationLevel = IsolationLevel.Serializable;
options.Timeout = TimeSpan.FromMinutes(2);
options.ScopeOption = TransactionScopeOption.RequiresNew;
});
?? How It Works
Once configured, all commands automatically execute within a transaction:
public class CreateOrderCommandHandler : ICommandHandler<CreateOrderCommand, OrderResult>
{
private readonly IOrderRepository _orderRepository;
private readonly IInventoryService _inventoryService;
public async Task<OrderResult> Handle(CreateOrderCommand command, CancellationToken ct)
{
// All operations are wrapped in a transaction
var order = await _orderRepository.CreateAsync(command);
await _inventoryService.ReserveItemsAsync(command.Items);
// ? Auto-commit on success
// ? Auto-rollback if any exception is thrown
return new OrderResult { OrderId = order.Id };
}
}
?? Excluding Commands from Transactions
Using the [NonTransactional] Attribute
[NonTransactional]
public class GetProductsQuery : ICommand<IEnumerable<Product>>
{
public string SearchTerm { get; set; }
}
Using Configuration
builder.Services.AddTransactionalBehavior(options =>
{
// Exclude specific command types
options.ExcludeCommand<ReadOnlyQuery>();
// Or exclude multiple at once
options.ExcludeCommands(
typeof(GetProductsQuery),
typeof(CacheRefreshCommand),
typeof(LoggingCommand)
);
});
?? Custom Transaction Context
For more control over transaction management (e.g., with Entity Framework Core):
1. Implement ITransactionalContext
public class EfCoreTransactionalContext : ITransactionalContext
{
private readonly ApplicationDbContext _context;
private IDbContextTransaction _transaction;
public EfCoreTransactionalContext(ApplicationDbContext context)
{
_context = context;
}
public async Task BeginTransactionAsync(CancellationToken ct = default)
{
_transaction = await _context.Database.BeginTransactionAsync(ct);
}
public async Task CommitAsync(CancellationToken ct = default)
{
await _context.SaveChangesAsync(ct);
await _transaction.CommitAsync(ct);
}
public async Task RollbackAsync(CancellationToken ct = default)
{
await _transaction.RollbackAsync(ct);
}
}
2. Register the Custom Context
builder.Services.AddTransactionalBehavior();
builder.Services.AddTransactionalContext<EfCoreTransactionalContext>();
?? Configuration Options
| Option | Default | Description |
|---|---|---|
IsolationLevel |
ReadCommitted |
Transaction isolation level |
Timeout |
30 seconds |
Transaction timeout duration |
ScopeOption |
Required |
Transaction scope behavior |
AsyncFlowOption |
Enabled |
Enables async flow for TransactionScope |
ExcludedCommandTypes |
Empty |
Commands to exclude from transactions |
Isolation Levels
options.IsolationLevel = IsolationLevel.ReadCommitted; // Default - good for most scenarios
options.IsolationLevel = IsolationLevel.Serializable; // Strictest - for financial transactions
options.IsolationLevel = IsolationLevel.ReadUncommitted; // Fastest - allows dirty reads
options.IsolationLevel = IsolationLevel.RepeatableRead; // Prevents non-repeatable reads
options.IsolationLevel = IsolationLevel.Snapshot; // Optimistic concurrency
Transaction Scope Options
options.ScopeOption = TransactionScopeOption.Required; // Join existing or create new (default)
options.ScopeOption = TransactionScopeOption.RequiresNew; // Always create a new transaction
options.ScopeOption = TransactionScopeOption.Suppress; // Execute without a transaction
?? Pipeline Behavior Order
When using multiple pipeline behaviors, consider the registration order:
builder.Services.AddCortexMediator(
new[] { typeof(Program) },
options =>
{
// 1. Validation first (fail fast before transaction starts)
options.AddFluentValidationBehaviors();
// 2. Transaction wraps the actual execution
options.AddTransactionalBehaviors();
// 3. Logging (optional)
options.AddDefaultBehaviors();
}
);
?? Best Practices
? Keep Transactions Short
// Good: Only database operations
public async Task<Result> Handle(Command command, CancellationToken ct)
{
await _repository.SaveAsync(entity);
return Result.Success();
}
// Avoid: External calls inside transactions
public async Task<Result> Handle(Command command, CancellationToken ct)
{
await _repository.SaveAsync(entity);
await _emailService.SendAsync(email); // ? External service call
return Result.Success();
}
? Exclude Read-Only Operations
[NonTransactional]
public class GetUserByIdQuery : ICommand<UserDto>
{
public int UserId { get; set; }
}
? Use Appropriate Isolation Levels
// High-throughput reads
options.IsolationLevel = IsolationLevel.ReadCommitted;
// Financial transactions
options.IsolationLevel = IsolationLevel.Serializable;
? Set Appropriate Timeouts
// Quick operations
options.Timeout = TimeSpan.FromSeconds(15);
// Complex batch operations
options.Timeout = TimeSpan.FromMinutes(5);
?? Documentation
For complete documentation, see the WIKI.md file.
?? Contributing
We welcome contributions! See the main Cortex repository for contribution guidelines.
?? License
This project is licensed under the MIT License.
?? Contact
- Email: cortex@buildersoft.io
- Website: https://buildersoft.io
- GitHub Issues: Cortex Data Framework Issues
- Discord:
Built with ?? by the Buildersoft team.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Cortex.Mediator (>= 3.1.2)
-
net8.0
- Cortex.Mediator (>= 3.1.2)
-
net9.0
- Cortex.Mediator (>= 3.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release of Cortex.Mediator.Behaviors.Transactional - Provides transactional pipeline behaviors for atomic command execution.