Entity Framework Core implementation for MinimalCleanArch (repositories, unit of work, specifications, DbContext helpers).
- Current stable: 0.1.19-preview (net9.0, net10.0).
- implement repository and unit-of-work patterns with EF Core instead of hand-rolling the infrastructure layer
- use audited and soft-delete-aware base DbContexts that line up with the MCA domain abstractions
- execute MCA specifications against EF Core without leaking query logic into handlers or controllers
- use it when your application persists MCA domain models through EF Core and you want MCA repository/specification support on top
- keep it in the infrastructure project where DbContext, migrations, and repository implementations live
- skip it if you are using another persistence technology or you want to implement repository abstractions yourself
- Depends on:
MinimalCleanArch - Typically referenced by: infrastructure projects
- Used by: API/host projects indirectly through your infrastructure project
- Do not reference from: pure domain projects; application projects should normally depend on repository abstractions, not on this package
DbContextBaseandIdentityDbContextBasewith auditing/soft-delete support.Repository<TEntity,TKey>andUnitOfWorkimplementations.SpecificationEvaluatorto translate specifications (including composedAnd/Or/Not) to EF Core queries and honorIsCountOnly,AsSplitQuery, andIgnoreQueryFilters.- DI extensions to register repositories/unit of work.
- Common repository query methods such as
AnyAsync,SingleOrDefaultAsync, andCountAsync(ISpecification<T>). - optional execution-context-aware base constructors for user and tenant-aware stamping
builder.Services.AddDbContext<AppDbContext>(opt => opt.UseSqlite("Data Source=app.db"));
builder.Services.AddScoped<DbContext>(sp => sp.GetRequiredService<AppDbContext>());
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped(typeof(IRepository<,>), typeof(Repository<,>));If you need a custom unit of work and access to IServiceProvider while configuring the DbContext:
builder.Services.AddMinimalCleanArch<AppDbContext, AppDbContext>((sp, options) =>
{
options.UseSqlite("Data Source=app.db");
});Recommended DbContext base usage:
public sealed class AppDbContext : DbContextBase
{
public AppDbContext(
DbContextOptions<AppDbContext> options,
IExecutionContext? executionContext = null)
: base(options, executionContext)
{
}
}Use the constructor overload that accepts IExecutionContext when you want audit stamping to flow from the current HTTP request or message-handler scope without overriding GetCurrentUserId().
public sealed class IncompleteHighPrioritySpec : BaseSpecification<Todo>
{
public IncompleteHighPrioritySpec()
{
AddCriteria(t => !t.IsCompleted && t.Priority >= 3);
ApplyOrderByDescending(t => t.Priority);
UseNoTracking();
}
}
// Compose and run
var dueToday = new DueTodaySpec();
var spec = new IncompleteHighPrioritySpec().And(dueToday);
var todos = await repository.GetAsync(spec, cancellationToken);
var hasAny = await repository.AnyAsync(spec, cancellationToken);
var total = await repository.CountAsync(spec, cancellationToken);
public sealed class DueTodaySpec : BaseSpecification<Todo>
{
public DueTodaySpec() : base(t => t.DueDate != null && t.DueDate.Value.Date == DateTime.UtcNow.Date)
{
}
}Use specifications through IRepository<TEntity, TKey> in application code. Treat SpecificationEvaluator as infrastructure-level plumbing for repository implementations and advanced EF integration points.
When using a locally built package, add a nuget.config pointing to your local feed (e.g., artifacts/nuget) before restoring.