EfTune 1.0.0
dotnet add package EfTune --version 1.0.0
NuGet\Install-Package EfTune -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EfTune" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EfTune" Version="1.0.0" />
<PackageReference Include="EfTune" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EfTune --version 1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: EfTune, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EfTune@1.0.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EfTune&version=1.0.0
#tool nuget:?package=EfTune&version=1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
EfTune
EfTune is a lightweight, extensible EF Core enhancement toolkit that brings interceptors, UTC conversion, auditing, value object support, domain event dispatching, soft delete handling, and more — all designed with clean architecture and modular design in mind.
"Enhance EF Core without the bloat. Just tune what you need."
✨ Features
- ✅
ISaveChangesInterceptor
-based composite pipeline - 🌐 Automatic UTC Conversion with
[AutoUtc]
support - 🕓 Audit Fields (
CreatedAt
,UpdatedAt
,CreatedBy
,UpdatedBy
) - 🔁 Soft Delete Interceptor + Global Query Filters
- 🧩 Value Object Conversion (
HasConversion<TValueObject, Primitive>
) - 📥 Seed Helpers (
SeedIfEmpty
,SeedFromEnum
) - 🔍 Global Query Filters for interfaces like
ITenantScoped
- 🕓 RowVersion / Concurrency Token Automation
- 🪝 Domain Event Dispatcher with outbox compatibility
- ✅ Minimal setup, maximum flexibility
📦 Installation
dotnet add package Moongazing.EfTune
🛠️ Setup
In your Program.cs or Startup.cs:
services.AddEfTune(x => x
.EnableUtc()
.EnableAudit()
.EnableSoftDelete()
.EnableDomainEvents()
);
If you're using domain events:
services.AddScoped<IDomainEventPublisher, YourEventPublisher>();
🧱 Interfaces
IAuditableEntity
public interface IAuditableEntity
{
DateTime CreatedAt { get; set; }
DateTime UpdatedAt { get; set; }
string? CreatedBy { get; set; }
string? UpdatedBy { get; set; }
}
ISoftDeletable
public interface ISoftDeletable
{
bool IsDeleted { get; set; }
}
IHasRowVersion
public interface IHasRowVersion
{
byte[] RowVersion { get; set; }
}
IDomainEvent & IHasDomainEvents
public interface IDomainEvent
{
DateTime OccurredOn { get; }
}
public interface IHasDomainEvents
{
List<IDomainEvent> DomainEvents { get; }
void ClearDomainEvents() => DomainEvents.Clear();
}
🧠 ModelBuilder Extensions
In your DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.UseSoftDelete()
.UseGlobalFilter<ITenantScoped>(e => e.TenantId == tenantId)
.UseConcurrencyTokens();
}
🎯 Value Object Mapping
modelBuilder.Entity<User>()
.HasSimpleValueObjectConversion(u => u.Email);
Or custom:
modelBuilder.Entity<User>()
.HasValueObjectConversion(
u => u.Email,
vo => vo.Value,
val => new Email(val)
);
🧪 Seeding
await db.SeedIfEmptyAsync(new[]
{
new Category { Id = 1, Name = "Books" }
});
await db.SeedFromEnumAsync<RoleType, Role>(e => new Role
{
Id = (int)(object)e,
Name = e.ToString()
});
🪝 Domain Events
Entity
public class Order : IHasDomainEvents
{
public List<IDomainEvent> DomainEvents { get; } = new();
public void AddCreatedEvent() => DomainEvents.Add(new OrderCreated(Id));
}
Event
public record OrderCreated(Guid OrderId) : IDomainEvent
{
public DateTime OccurredOn { get; } = DateTime.UtcNow;
}
Publisher (example)
public class ConsolePublisher : IDomainEventPublisher
{
public Task PublishAsync(IDomainEvent @event, CancellationToken ct = default)
{
Console.WriteLine($"Published: {@event.GetType().Name}");
return Task.CompletedTask;
}
}
💡 Philosophy
EfTune is built with:
Clean architecture principles
Modularity & composability
Convention over configuration
Production-readiness with minimal friction
🛠️ Roadmap
Version Features
v1.0 Interceptor system, UTC, Audit, Seed, ValueObject
v1.1 Soft Delete, QueryFilter, RowVersion, Domain Events
v1.2 Outbox Dispatcher, Change Log Interceptor, Dev Logger
v2.0 CLI Tooling, Background Processor, Telemetry Integration
📄 License
MIT © Tunahan Ali Öztürk
⭐ GitHub
https://github.com/Moongazing/EfTune
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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 was computed. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net9.0
- Microsoft.EntityFrameworkCore (>= 9.0.6)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.0.0 | 94 | 7/4/2025 |