DKNet.EfCore.Specifications 9.5.28

dotnet add package DKNet.EfCore.Specifications --version 9.5.28
                    
NuGet\Install-Package DKNet.EfCore.Specifications -Version 9.5.28
                    
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="DKNet.EfCore.Specifications" Version="9.5.28" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DKNet.EfCore.Specifications" Version="9.5.28" />
                    
Directory.Packages.props
<PackageReference Include="DKNet.EfCore.Specifications" />
                    
Project file
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 DKNet.EfCore.Specifications --version 9.5.28
                    
#r "nuget: DKNet.EfCore.Specifications, 9.5.28"
                    
#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 DKNet.EfCore.Specifications@9.5.28
                    
#: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=DKNet.EfCore.Specifications&version=9.5.28
                    
Install as a Cake Addin
#tool nuget:?package=DKNet.EfCore.Specifications&version=9.5.28
                    
Install as a Cake Tool

DKNet.EfCore.Specifications

A flexible and reusable implementation of the Specification Pattern for Entity Framework Core, providing clean data access without the overhead of traditional repository patterns.

Overview

This library provides a powerful way to build flexible and reusable database queries in .NET projects. Define reusable filters, includes, and sorting as specification classes, avoiding the problems that come with large, hard-to-maintain repositories.

Features

  • Specification Pattern: Build complex queries using composable specification objects
  • Repository Pattern: Optional IRepositorySpec interface for common CRUD operations
  • Type-Safe Queries: Strongly-typed query specifications with IntelliSense support
  • Flexible Filtering: Define reusable filter criteria
  • Include Support: Eagerly load related entities
  • Sorting: Support for both ascending and descending ordering
  • Query Filter Control: Ability to ignore global query filters (e.g., soft delete, multi-tenancy)
  • Projection Support: Map entities to DTOs using Mapster integration

Installation

dotnet add package DKNet.EfCore.Specifications

Core Components

ISpecification<TEntity>

The base specification interface that defines:

  • FilterQuery: Filtering function to test each element for a condition
  • IncludeQueries: Collection of functions describing included entities
  • OrderByQueries: Functions for ascending ordering
  • OrderByDescendingQueries: Functions for descending ordering
  • IgnoreQueryFilters: Flag to ignore global query filters

Specification<TEntity>

Abstract base class for creating custom specifications:

public class ActiveUsersSpecification : Specification<User>
{
    public ActiveUsersSpecification()
    {
        WithFilter(u => u.IsActive);
        AddInclude(u => u.Profile);
        AddOrderBy(u => u.LastName);
    }
}

IRepositorySpec

Interface for repository operations with specification support:

Query Operations
  • Query<TEntity>(spec): Query entities using a specification
  • Query<TEntity, TModel>(spec): Query and project to a model type
Transaction Management
  • BeginTransactionAsync(): Start a new database transaction
  • Entry<TEntity>(entity): Access entity change tracking information
CRUD Operations
  • AddAsync<TEntity>(entity): Add a single entity
  • AddRangeAsync<TEntity>(entities): Add multiple entities
  • UpdateAsync<TEntity>(entity): Update an entity and handle navigation properties
  • UpdateRangeAsync<TEntity>(entities): Update multiple entities
  • Delete<TEntity>(entity): Mark entity for deletion
  • DeleteRange<TEntity>(entities): Mark multiple entities for deletion
  • SaveChangesAsync(): Persist all changes to the database

RepositorySpec<TDbContext>

Concrete implementation of IRepositorySpec with:

  • Automatic handling of new entities from navigation properties during updates
  • Mapster integration for entity-to-DTO projections
  • Support for query filters and change tracking

Usage Examples

Creating a Specification

public class UsersByRoleSpecification : Specification<User>
{
    public UsersByRoleSpecification(string role)
    {
        // Define filter criteria
        WithFilter(u => u.Role == role && u.IsActive);
        
        // Include related entities
        AddInclude(u => u.Profile);
        AddInclude(u => u.Orders);
        
        // Define ordering
        AddOrderBy(u => u.LastName);
        AddOrderBy(u => u.FirstName);
    }
}

Using Specifications with IRepositorySpec

public class UserService
{
    private readonly IRepositorySpec _repository;
    
    public UserService(IRepositorySpec repository)
    {
        _repository = repository;
    }
    
    public async Task<List<User>> GetActiveAdmins()
    {
        var spec = new UsersByRoleSpecification("Admin");
        return await _repository.Query(spec).ToListAsync();
    }
    
    public async Task<List<UserDto>> GetActiveAdminsAsDto()
    {
        var spec = new UsersByRoleSpecification("Admin");
        return await _repository.Query<User, UserDto>(spec).ToListAsync();
    }
}

CRUD Operations

// Add a new entity
var user = new User { FirstName = "John", LastName = "Doe" };
await _repository.AddAsync(user);
await _repository.SaveChangesAsync();

// Update an entity
user.IsActive = false;
await _repository.UpdateAsync(user);
await _repository.SaveChangesAsync();

// Delete an entity
_repository.Delete(user);
await _repository.SaveChangesAsync();

// Transaction support
using var transaction = await _repository.BeginTransactionAsync();
try
{
    await _repository.AddAsync(newUser);
    await _repository.SaveChangesAsync();
    await transaction.CommitAsync();
}
catch
{
    await transaction.RollbackAsync();
    throw;
}

Ignoring Query Filters

public class AllUsersIncludingSoftDeletedSpecification : Specification<User>
{
    public AllUsersIncludingSoftDeletedSpecification()
    {
        IgnoreQueryFiltersEnabled();
        AddOrderBy(u => u.CreatedDate);
    }
}

Complex Filtering with PredicateBuilder

public class DynamicUserSearchSpecification : Specification<User>
{
    public DynamicUserSearchSpecification(string? name, bool? isActive)
    {
        var predicate = CreatePredicate();
        
        if (!string.IsNullOrEmpty(name))
            predicate = predicate.And(u => u.FirstName.Contains(name) || u.LastName.Contains(name));
            
        if (isActive.HasValue)
            predicate = predicate.And(u => u.IsActive == isActive.Value);
            
        WithFilter(predicate);
    }
}

Dependency Injection Setup

services.AddDbContext<MyDbContext>(options => 
    options.UseNpgsql(connectionString));

services.AddScoped<IRepositorySpec, RepositorySpec<MyDbContext>>();

// For projection support, register Mapster
services.AddSingleton<IMapper>(new Mapper());

Benefits

  1. Reusability: Define query logic once, use it everywhere
  2. Testability: Easy to unit test specifications in isolation
  3. Maintainability: Query logic is centralized and versioned
  4. Type Safety: Compile-time checking of query expressions
  5. Separation of Concerns: Business logic separate from data access
  6. Performance: Optimized query execution with proper includes and filtering

Migration Notes

Breaking Changes in Latest Version:

  • AndSpecification and OrSpecification classes have been removed
  • Use LinqKit's PredicateBuilder for combining filter expressions instead
  • All methods in IRepositorySpec are now properly documented with XML comments

References

License

This library is part of the DKNet.FW framework.

Product 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.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on DKNet.EfCore.Specifications:

Package Downloads
DKNet.EfCore.Repos

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
9.5.28 0 10/27/2025
9.5.27 27 10/27/2025
9.5.26 29 10/27/2025
9.5.25 28 10/26/2025
9.5.24 33 10/25/2025
9.5.23 28 10/25/2025
9.5.22 39 10/25/2025
9.5.21 99 10/24/2025
9.5.20 114 10/23/2025
9.5.19 101 10/23/2025
9.5.18 108 10/22/2025
9.5.17 184 10/17/2025
9.5.16 130 10/17/2025
9.5.15 171 10/15/2025
9.5.14 170 10/14/2025
9.5.13 156 10/14/2025
9.5.12 156 10/14/2025
9.5.11 160 10/14/2025
9.5.10 179 10/14/2025
9.5.9 157 10/13/2025
9.5.8 98 10/11/2025
9.5.7 109 10/10/2025
9.5.6 112 10/10/2025
9.5.5 117 10/10/2025
9.5.4 126 10/10/2025
9.5.3 190 10/8/2025
9.5.2 153 10/8/2025
9.5.1 173 10/7/2025
9.0.42 161 10/6/2025
9.0.41 168 10/2/2025
9.0.40 136 9/27/2025
9.0.39 144 9/26/2025
9.0.38 170 9/24/2025
9.0.37 152 9/23/2025
9.0.36 183 9/23/2025
9.0.35 167 9/23/2025
9.0.34 171 9/23/2025
9.0.33 153 9/21/2025
9.0.32 153 9/21/2025
9.0.31 283 9/19/2025
9.0.30 287 9/18/2025
9.0.29 278 9/18/2025
9.0.28 299 9/17/2025
9.0.27 290 9/17/2025
9.0.26 287 9/16/2025
9.0.25 229 9/15/2025
9.0.24 235 9/15/2025