AuditaX 2.4.1
Requires NuGet 6.0 or higher.
dotnet add package AuditaX --version 2.4.1
NuGet\Install-Package AuditaX -Version 2.4.1
<PackageReference Include="AuditaX" Version="2.4.1" />
<PackageVersion Include="AuditaX" Version="2.4.1" />
<PackageReference Include="AuditaX" />
paket add AuditaX --version 2.4.1
#r "nuget: AuditaX, 2.4.1"
#:package AuditaX@2.4.1
#addin nuget:?package=AuditaX&version=2.4.1
#tool nuget:?package=AuditaX&version=2.4.1

AuditaX
Flexible Entity Audit Logging for .NET 10+
AuditaX is a modern, extensible audit logging library for .NET applications. It provides a unified approach to tracking entity changes across different ORMs and database providers, with support for both automatic and manual audit control.
Built exclusively for .NET 10 with C# 14, AuditaX offers fluent configuration, multiple serialization formats, and seamless integration with your existing data access layer.
💖 Support the Project
AuditaX is a passion project, driven by the desire to provide a truly modern audit logging solution for the .NET community. Maintaining this library requires significant effort: staying current with each .NET release, addressing issues promptly, implementing new features, keeping documentation up to date, and ensuring compatibility across different ORMs and database providers.
If AuditaX has helped you build better applications or saved you development time, I would be incredibly grateful for your support. Your contribution—no matter the size—helps me dedicate time to respond to issues quickly, implement improvements, and keep the library evolving alongside the .NET platform.
I'm also looking for sponsors who believe in this project's mission. Sponsorship helps ensure AuditaX remains actively maintained and continues to serve the .NET community for years to come.
Of course, there's absolutely no obligation. If you prefer, simply starring the repository or sharing AuditaX with fellow developers is equally appreciated!
⭐ Star the repository on GitHub to raise its visibility
💬 Share AuditaX with your team or community
☕ Support via Donations:
✨ Features
- Multiple ORM Support: Dapper and Entity Framework Core
- Multiple Database Providers: SQL Server and PostgreSQL
- Flexible Change Log Format: JSON or XML serialization
- Automatic Change Tracking: EF Core interceptors capture all changes
- Manual Audit Control:
IAuditUnitOfWorkfor Dapper repositories - Related Entities: Track child entity changes under parent audit log
- Lookup Properties: Resolve FK values to display names (e.g., RoleId → "Administrator")
- Configuration Options: appsettings.json or Fluent API
- Auto Table Creation: Creates audit table on startup if needed
- Startup Validation: Validates table structure and configuration
🎉 What's New in 2.0.0
Breaking change: IAuditQueryService, Response<T>, PagedResponse<T>, AuditQueryMessages, AuditQueryValidator, and all query models have been removed. AuditaX now focuses exclusively on audit registration. Querying the AuditLog table is the consumer's responsibility.
See CHANGELOG.md for the full migration guide.
📦 Packages
🚀 Getting Started
Installation
Choose packages based on your ORM and database:
For Dapper + SQL Server:
dotnet add package AuditaX
dotnet add package AuditaX.Dapper
dotnet add package AuditaX.SqlServer
For EF Core + PostgreSQL:
dotnet add package AuditaX
dotnet add package AuditaX.EntityFramework
dotnet add package AuditaX.PostgreSql
Configuration
Option A: appsettings.json
{
"AuditaX": {
"TableName": "AuditLog",
"Schema": "dbo",
"LogFormat": "Json",
"AutoCreateTable": true,
"EnableLogging": true,
"Entities": {
"Product": {
"Key": "Id",
"Properties": [ "Name", "Price", "Stock" ]
}
}
}
}
services.AddAuditaX(configuration)
.UseDapper<DapperContext>()
.UseSqlServer()
.ValidateOnStartup();
Option B: Fluent API
services.AddAuditaX(options =>
{
options.TableName = "AuditLog";
options.Schema = "dbo";
options.AutoCreateTable = true;
options.EnableLogging = true;
options.LogFormat = LogFormat.Json;
options.ConfigureEntity<Product>("Product")
.WithKey(p => p.Id)
.Properties("Name", "Price", "Stock");
})
.UseDapper<DapperContext>()
.UseSqlServer()
.ValidateOnStartup();
💻 Usage
With Dapper (Manual Audit)
Inject IAuditUnitOfWork into your repositories:
public class ProductRepository(DapperContext context, IAuditUnitOfWork audit)
{
public async Task<int> CreateAsync(Product product)
{
using var connection = context.CreateConnection();
const string sql = "INSERT INTO Products (...) OUTPUT INSERTED.ProductId VALUES (...)";
var id = await connection.QuerySingleAsync<int>(sql, product);
product.ProductId = id;
await audit.LogCreateAsync(product);
return id;
}
public async Task<int> UpdateAsync(Product original, Product updated)
{
using var connection = context.CreateConnection();
const string sql = "UPDATE Products SET ... WHERE ProductId = @ProductId";
var affected = await connection.ExecuteAsync(sql, updated);
if (affected > 0)
{
await audit.LogUpdateAsync(original, updated);
}
return affected;
}
public async Task<bool> DeleteAsync(Product product)
{
using var connection = context.CreateConnection();
const string sql = "DELETE FROM Products WHERE ProductId = @ProductId";
var affected = await connection.ExecuteAsync(sql, new { product.ProductId });
if (affected > 0)
{
await audit.LogDeleteAsync(product);
}
return affected > 0;
}
// Related entity operations
public async Task AddTagAsync(Product product, ProductTag tag)
{
using var connection = context.CreateConnection();
const string sql = "INSERT INTO ProductTags (ProductId, Tag) VALUES (@ProductId, @Tag)";
await connection.ExecuteAsync(sql, tag);
await audit.LogRelatedAddedAsync(product, tag);
}
public async Task UpdateTagAsync(Product product, ProductTag original, ProductTag modified)
{
using var connection = context.CreateConnection();
const string sql = "UPDATE ProductTags SET Tag = @Tag WHERE Id = @Id";
await connection.ExecuteAsync(sql, modified);
await audit.LogRelatedUpdatedAsync(product, original, modified);
}
public async Task RemoveTagAsync(Product product, ProductTag tag)
{
using var connection = context.CreateConnection();
const string sql = "DELETE FROM ProductTags WHERE Id = @Id";
await connection.ExecuteAsync(sql, new { tag.Id });
await audit.LogRelatedRemovedAsync(product, tag);
}
}
With Entity Framework Core (Automatic)
EF Core uses interceptors for automatic audit logging. Configure AuditaX first, then register your DbContext with the interceptor:
Step 1: Configure AuditaX
// Configure AuditaX BEFORE registering DbContext
services.AddAuditaX(options =>
{
options.TableName = "AuditLog";
options.Schema = "dbo";
options.AutoCreateTable = true;
options.LogFormat = LogFormat.Json;
options.ConfigureEntity<Product>("Product")
.WithKey(p => p.Id)
.Properties("Name", "Price", "Stock");
})
.UseEntityFramework<AppDbContext>()
.UseSqlServer()
.ValidateOnStartup();
Step 2: Register DbContext with AuditaX
// IMPORTANT: Use (sp, options) to access the service provider
services.AddDbContext<AppDbContext>((sp, options) =>
{
options.UseSqlServer(connectionString);
// This line enables automatic audit logging
options.UseAuditaX(sp);
});
Note: The call to
UseAuditaX(sp)is required for automatic change tracking. Without it, entity changes will not be audited.
Important: AuditaX requires EF Core's ChangeTracker to detect entity changes. Do NOT use
QueryTrackingBehavior.NoTrackingin your DbContext, as this disables change tracking and AuditaX will not be able to audit entity modifications.
Step 3: Use your DbContext normally
// Entity changes are automatically tracked - no manual logging needed!
var product = new Product { Name = "Widget", Price = 9.99m };
dbContext.Products.Add(product);
await dbContext.SaveChangesAsync(); // Audit log created automatically
product.Price = 12.99m;
await dbContext.SaveChangesAsync(); // Update audit log created automatically
🗄️ Audit Log Structure
SQL Server
| Column | JSON Format | XML Format |
|---|---|---|
LogId |
UNIQUEIDENTIFIER | UNIQUEIDENTIFIER |
SourceName |
NVARCHAR(64) | NVARCHAR(64) |
SourceKey |
NVARCHAR(64) | NVARCHAR(64) |
AuditLog |
NVARCHAR(MAX) | XML |
PostgreSQL
| Column | JSON Format | XML Format |
|---|---|---|
log_id |
UUID | UUID |
source_name |
VARCHAR(64) | VARCHAR(64) |
source_key |
VARCHAR(64) | VARCHAR(64) |
audit_log |
JSONB | XML |
📋 Change Log Formats
JSON Format
{
"auditLog": [
{
"action": "Created",
"user": "demo@auditax.sample",
"timestamp": "2025-12-11T12:55:38.4907999Z"
},
{
"action": "Updated",
"user": "demo@auditax.sample",
"timestamp": "2025-12-11T12:55:38.6169691Z",
"fields": [
{ "name": "Price", "before": "79.99", "after": "69.99" },
{ "name": "Stock", "before": "100", "after": "95" }
]
},
{
"action": "Added",
"user": "demo@auditax.sample",
"timestamp": "2025-12-11T12:55:38.6777639Z",
"related": "ProductTag",
"fields": [
{ "name": "Tag", "value": "Gaming" }
]
},
{
"action": "Removed",
"user": "demo@auditax.sample",
"timestamp": "2025-12-11T12:55:38.7375026Z",
"related": "ProductTag",
"fields": [
{ "name": "Tag", "value": "Gaming" }
]
},
{
"action": "Deleted",
"user": "demo@auditax.sample",
"timestamp": "2025-12-11T12:55:38.7575026Z"
}
]
}
XML Format
<AuditLog>
<Entry Action="Created" User="demo@auditax.sample" Timestamp="2025-12-12T14:38:01.9671416Z" />
<Entry Action="Updated" User="demo@auditax.sample" Timestamp="2025-12-12T14:41:12.5715243Z">
<Field Name="Price" Before="9.99" After="12.99" />
<Field Name="Stock" Before="100" After="85" />
</Entry>
<Entry Action="Added" User="demo@auditax.sample" Timestamp="2025-12-12T14:42:00.1234567Z" Related="ProductTag">
<Field Name="Tag" Value="Gaming" />
</Entry>
<Entry Action="Removed" User="demo@auditax.sample" Timestamp="2025-12-12T14:43:00.1234567Z" Related="ProductTag">
<Field Name="Tag" Value="Gaming" />
</Entry>
<Entry Action="Deleted" User="demo@auditax.sample" Timestamp="2025-12-12T14:44:00.1234567Z" />
</AuditLog>
📚 Documentation
See the docs folder for detailed documentation:
Guides:
- Dapper Audit Guide - Complete guide to manual auditing with Dapper
- Related Entities and Lookups - Track child entities and resolve FK values Configuration by Stack:
- Dapper + SQL Server + JSON
- Dapper + SQL Server + XML
- Dapper + PostgreSQL + JSON
- Dapper + PostgreSQL + XML
- EF Core + SQL Server + JSON
- EF Core + SQL Server + XML
- EF Core + PostgreSQL + JSON
- EF Core + PostgreSQL + XML
🧪 Samples
The samples folder contains working examples:
AuditaX.Sample.Dapper- Console app demonstrating Dapper integrationAuditaX.Sample.EntityFramework- Console app demonstrating EF Core integration
Database Setup
Use the DatabaseSetup tool to create sample databases:
# Create both SQL Server and PostgreSQL databases
dotnet run --project tools/AuditaX.Tools.DatabaseSetup -- all
# Create SQL Server only
dotnet run --project tools/AuditaX.Tools.DatabaseSetup -- sqlserver
# Create PostgreSQL only
dotnet run --project tools/AuditaX.Tools.DatabaseSetup -- postgresql
This creates:
- SQL Server:
AuditaXdatabase with Products, ProductTags, Users, Roles, UserRoles tables - PostgreSQL:
auditaxdatabase with the same tables (snake_case naming)
AuditLog tables are created automatically by AuditaX when AutoCreateTable = true.
📅 Versioning & .NET Support Policy
AuditaX follows a clear versioning strategy aligned with .NET's release cadence:
| AuditaX | .NET | C# | Status |
|---|---|---|---|
| 2.x | .NET 10 | C# 14 | Current |
Future Support Policy
AuditaX will always support the current LTS version plus the next standard release. When a new LTS version is released, support for older versions will be discontinued:
| AuditaX | .NET | C# | Notes |
|---|---|---|---|
| 2.x | .NET 10 | C# 14 | LTS only |
| 2.x | .NET 10 + .NET 11 | C# 14 / C# 15 | LTS + Standard |
| 3.x | .NET 12 | C# 16 | New LTS (drops .NET 10/11) |
| 4.x | .NET 12 + .NET 13 | C# 16 / C# 17 | LTS + Standard |
Why this policy?
- Focused development: By limiting supported versions, we can dedicate more effort to quality, performance, and new features
- Modern features: Each .NET version brings improvements that AuditaX can fully leverage
- Clear upgrade path: Users know exactly when to plan their upgrades
Note: We recommend always using the latest LTS version of .NET for production applications.
⚙️ Requirements
- .NET 10.0 or later
- SQL Server 2016+ or PostgreSQL 12+
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.8)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Options (>= 10.0.8)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on AuditaX:
| Package | Downloads |
|---|---|
|
AuditaX.SqlServer
SQL Server database provider for AuditaX audit logging with optimized queries and native type support. |
|
|
AuditaX.Dapper
Dapper ORM integration for AuditaX with IAuditUnitOfWork for manual audit control in lightweight data access scenarios. |
|
|
AuditaX.EntityFramework
Entity Framework Core integration for AuditaX with automatic change tracking via SaveChanges interceptors. |
|
|
AuditaX.PostgreSql
PostgreSQL database provider for AuditaX audit logging with optimized queries and native type support. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.4.1 | 618 | 6/10/2026 |
| 2.4.0 | 523 | 5/29/2026 |
| 2.3.1 | 592 | 5/25/2026 |
| 2.3.0 | 330 | 5/25/2026 |
| 2.2.1 | 345 | 5/25/2026 |
| 2.2.0 | 334 | 5/20/2026 |
| 2.1.0 | 374 | 5/1/2026 |
| 2.0.0 | 651 | 3/9/2026 |
| 1.2.4 | 332 | 3/9/2026 |
| 1.2.3 | 338 | 3/7/2026 |
| 1.2.2 | 342 | 3/3/2026 |
| 1.2.1 | 373 | 2/24/2026 |
| 1.2.0 | 384 | 2/24/2026 |
| 1.1.1 | 382 | 2/24/2026 |
| 1.1.0 | 405 | 2/21/2026 |
| 1.0.4 | 368 | 2/10/2026 |
| 1.0.3 | 611 | 12/17/2025 |
2.4.0: IAuditService now accepts an optional sourceReference on the user overloads of LogCreate/LogUpdate/LogDelete/LogRelated, and AuditService persists it (sets it on new AuditLog rows and refreshes it on existing ones). This lets the Dapper path populate SourceReference, matching the EF interceptor behavior. 2.3.1: Republish bump of 2.3.0 (version-only change). 2.3.0: SourceReference column widened to 512 chars; BREAKING: existing AuditLog tables must ALTER SourceReference to width >= 512.