Innovabit.DotNet.Interceptors.Transactions.Abstractions
2.0.117
dotnet add package Innovabit.DotNet.Interceptors.Transactions.Abstractions --version 2.0.117
NuGet\Install-Package Innovabit.DotNet.Interceptors.Transactions.Abstractions -Version 2.0.117
<PackageReference Include="Innovabit.DotNet.Interceptors.Transactions.Abstractions" Version="2.0.117" />
<PackageVersion Include="Innovabit.DotNet.Interceptors.Transactions.Abstractions" Version="2.0.117" />
<PackageReference Include="Innovabit.DotNet.Interceptors.Transactions.Abstractions" />
paket add Innovabit.DotNet.Interceptors.Transactions.Abstractions --version 2.0.117
#r "nuget: Innovabit.DotNet.Interceptors.Transactions.Abstractions, 2.0.117"
#:package Innovabit.DotNet.Interceptors.Transactions.Abstractions@2.0.117
#addin nuget:?package=Innovabit.DotNet.Interceptors.Transactions.Abstractions&version=2.0.117
#tool nuget:?package=Innovabit.DotNet.Interceptors.Transactions.Abstractions&version=2.0.117
Innovabit.DotNet.Interceptors.Transactions.Abstractions
Declarative database transactions for Innovabit.DotNet.Interceptors
via a [Transactional] attribute. This is the provider-agnostic base: it ships the interceptor,
the attribute and the ITransactionManager abstraction. Pick a provider to actually open
transactions:
Innovabit.DotNet.Interceptors.Transactions.EntityFrameworkCore— on aDbContext.Innovabit.DotNet.Interceptors.Transactions.SystemTransactions— onTransactionScope.Innovabit.DotNet.Interceptors.Transactions.AdoNet— on a rawDbConnection(Dapper, ADO.NET).
Usage
services
.AddInterceptors()
.AddEntityFrameworkCoreTransactions<OrderDbContext>(); // or .AddTransactionScope() / .AddAdoNetTransactions()
services.AddScopedWithInterception<IOrderService, OrderService>();
public class OrderService(OrderDbContext db) : IOrderService
{
// One transaction around the whole method: committed on return, rolled back on exception.
[Transactional]
public async Task PlaceAsync(Order order, CancellationToken cancellationToken)
{
db.Orders.Add(order);
await db.SaveChangesAsync(cancellationToken);
// Joins the transaction above — nothing is persisted unless both steps succeed.
await _inventory.ReserveAsync(order, cancellationToken);
}
}
The method's own CancellationToken argument (if it has one) is flowed into the commit/rollback,
so a cancelled call does not leave transaction work running past it.
Lifetimes
Register the interceptors scoped — AddInterceptors() with no argument, which is the default.
Providers register their ITransactionManager as scoped (a DbContext or a connection is scoped),
so AddInterceptors(ServiceLifetime.Singleton) would make the interceptor a captive of a scoped
dependency and DI fails at resolution. Resolve the intercepted service from a scope, the way a web
request or a message handler already does.
[Transactional]
| Property | Meaning |
|---|---|
Propagation |
How to behave when a transaction is already in progress. Defaults to Required. |
IsolationLevel |
Isolation level for a transaction this method starts. Defaults to Unspecified (provider decides). |
TimeoutSeconds |
Maximum lifetime of the transaction. 0 = the provider's default. |
ReadOnly |
Open the transaction but always finish it with a rollback. |
RollbackOn |
Exception types that roll back. Unset = every exception rolls back. |
NoRollbackOn |
Exception types that must not roll back. Wins over RollbackOn. |
Propagation
| Value | Transaction already in progress | No transaction in progress |
|---|---|---|
Required (default) |
Join it | Start one |
RequiresNew |
Start an independent one | Start one |
Supports |
Join it | Run without a transaction |
Mandatory |
Join it | Throw InvalidOperationException |
Never |
Throw InvalidOperationException |
Run without a transaction |
Not every provider can nest transactions: RequiresNew throws NotSupportedException on the
Entity Framework Core and ADO.NET providers (a single connection cannot hold two independent
transactions). Use the TransactionScope provider when you need it.
Read-only methods
[Transactional(ReadOnly = true)] still opens a transaction — so a multi-query read sees one
consistent snapshot — but always finishes it with a rollback. A write that slips into a read path
therefore never reaches the database instead of being silently committed.
Selective rollback
// The order row survives: a rejected payment is a business outcome worth persisting.
[Transactional(NoRollbackOn = new[] { typeof(PaymentDeclinedException) })]
public Task ChargeAsync(Guid orderId) { ... }
NoRollbackOn takes precedence over RollbackOn, so a broad rule can be narrowed with specific
exclusions. The exception is re-thrown either way — the choice is only about committing or undoing
the work already done.
Ordering
The interceptor runs at InterceptorOrders.Transaction (700), the innermost position on the
default scale. That matters when it is combined with retry (500): each retry attempt gets its own
fresh transaction, instead of reusing one the previous failure already poisoned.
Writing a provider
Implement ITransactionManager (plus the ITransaction handle it returns) and register it in DI
alongside AddTransactions():
public static InterceptorBuilder AddMyTransactions(this InterceptorBuilder builder)
{
builder.Services.TryAddScoped<ITransactionManager, MyTransactionManager>();
return builder.AddTransactions();
}
The interceptor — not the manager — applies the propagation rules: it reads
ITransactionManager.HasActiveTransaction and only calls Begin/BeginAsync when a new
transaction must be opened. A manager that cannot nest should throw NotSupportedException when
TransactionSettings.Propagation is RequiresNew.
License
MIT
| 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
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.117)
-
net8.0
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.117)
-
net9.0
- Innovabit.DotNet.Interceptors.Abstractions (>= 2.0.117)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Innovabit.DotNet.Interceptors.Transactions.Abstractions:
| Package | Downloads |
|---|---|
|
Innovabit.DotNet.Interceptors.Transactions.SystemTransactions
TransactionScope (System.Transactions) provider for interceptor-based [Transactional] methods. |
|
|
Innovabit.DotNet.Interceptors.Transactions.AdoNet
ADO.NET (DbConnection / Dapper) transaction provider for interceptor-based [Transactional] methods. |
|
|
Innovabit.DotNet.Interceptors.Transactions.EntityFrameworkCore
Entity Framework Core transaction provider for interceptor-based [Transactional] methods. |
|
|
Innovabit.DotNet.Interceptors.All
Meta-package: every interceptor concern in the suite (logging, validation, caching, notifications, telemetry, audit, authorization, rate limiting, coordination, feature gates, transactions, retry/timeout/circuit breaker/fallback) in one reference. Providers are separate packages — pick the ones you use. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.117 | 0 | 10/31/2026 |
| 2.0.116 | 148 | 10/26/2026 |
| 2.0.115 | 165 | 10/17/2026 |
| 2.0.114 | 160 | 10/10/2026 |
| 2.0.113 | 168 | 10/3/2026 |
| 2.0.112 | 171 | 9/28/2026 |
| 2.0.111 | 160 | 9/28/2026 |
| 2.0.110 | 164 | 9/27/2026 |
| 2.0.109 | 156 | 9/26/2026 |
| 2.0.108 | 160 | 9/26/2026 |
| 2.0.107 | 165 | 9/26/2026 |
| 2.0.106 | 165 | 9/25/2026 |
| 2.0.105 | 165 | 9/25/2026 |
| 1.0.0.104 | 149 | 9/25/2026 |
| 1.0.0.103 | 146 | 9/25/2026 |
| 1.0.0.102 | 146 | 9/25/2026 |
| 1.0.0.101 | 144 | 9/25/2026 |
| 1.0.0.100 | 150 | 9/25/2026 |
| 1.0.0.99 | 156 | 9/25/2026 |