FS.EntityFramework.Library 9.0.6.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package FS.EntityFramework.Library --version 9.0.6.1
                    
NuGet\Install-Package FS.EntityFramework.Library -Version 9.0.6.1
                    
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="FS.EntityFramework.Library" Version="9.0.6.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FS.EntityFramework.Library" Version="9.0.6.1" />
                    
Directory.Packages.props
<PackageReference Include="FS.EntityFramework.Library" />
                    
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 FS.EntityFramework.Library --version 9.0.6.1
                    
#r "nuget: FS.EntityFramework.Library, 9.0.6.1"
                    
#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 FS.EntityFramework.Library@9.0.6.1
                    
#: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=FS.EntityFramework.Library&version=9.0.6.1
                    
Install as a Cake Addin
#tool nuget:?package=FS.EntityFramework.Library&version=9.0.6.1
                    
Install as a Cake Tool

FS.EntityFramework.Library

A comprehensive Entity Framework Core library providing Repository pattern, Unit of Work, Specification pattern, dynamic filtering, and pagination support for .NET applications.

📋 Table of Contents

Features

  • 🏗️ Repository Pattern: Generic repository implementation with advanced querying capabilities
  • 🔄 Unit of Work Pattern: Coordinate multiple repositories and manage transactions
  • 📋 Specification Pattern: Flexible and reusable query specifications
  • 🔍 Dynamic Filtering: Build dynamic queries from filter models
  • 📄 Pagination: Built-in pagination support with metadata
  • 🏷️ Base Entities: Pre-built base classes for entities with audit properties
  • 🔒 Soft Delete: Built-in soft delete functionality
  • Automatic Audit: Automatic CreatedAt, UpdatedAt, DeletedAt tracking
  • 👤 User Tracking: Automatic CreatedBy, UpdatedBy, DeletedBy tracking
  • 💉 Dependency Injection: Easy integration with DI containers
  • 🔧 Flexible User Context: Works with any user service implementation

Installation

dotnet add package FS.EntityFramework.Library

Quick Start

1. Configure Services

Basic Setup (without audit)
services.AddDbContext<YourDbContext>(options =>
    options.UseSqlServer(connectionString));

services.AddGenericUnitOfWork<YourDbContext>();
With Automatic Audit Support

Option A: Using your existing user service

// If you have your own ICurrentUserService
services.AddScoped<ICurrentUserService, CurrentUserService>();

services.AddGenericUnitOfWorkWithAudit<YourDbContext>(
    provider => provider.GetRequiredService<ICurrentUserService>().UserId);

Option B: Using HttpContext directly

services.AddHttpContextAccessor();

services.AddGenericUnitOfWorkWithAudit<YourDbContext>(
    provider =>
    {
        var httpContextAccessor = provider.GetRequiredService<IHttpContextAccessor>();
        return httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    });

Option C: Using IUserContext interface

public class MyUserContext : IUserContext
{
    public MyUserContext(ICurrentUserService currentUserService)
    {
        CurrentUser = currentUserService.UserId;
    }
    
    public string? CurrentUser { get; }
}

services.AddScoped<IUserContext, MyUserContext>();
services.AddGenericUnitOfWorkWithAudit<YourDbContext, MyUserContext>();

2. Create Your Entities

public class Product : BaseAuditableEntity<int>
{
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public string Description { get; set; } = string.Empty;
}

// When you save a product, these properties are automatically set:
// - CreatedAt: DateTime.UtcNow (when entity is first created)
// - CreatedBy: Current user ID (from your user context)
// - UpdatedAt: DateTime.UtcNow (when entity is modified)
// - UpdatedBy: Current user ID (when entity is modified)
// - IsDeleted: false/true (for soft deletes)
// - DeletedAt: DateTime.UtcNow (when entity is soft deleted)
// - DeletedBy: Current user ID (when entity is soft deleted)

3. Use in Your Services

public class ProductService
{
    private readonly IUnitOfWork _unitOfWork;

    public ProductService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task<Product> CreateProductAsync(Product product)
    {
        var repository = _unitOfWork.GetRepository<Product, int>();
        await repository.AddAsync(product);
        await _unitOfWork.SaveChangesAsync();
        return product;
    }

    public async Task<IPaginate<Product>> GetProductsAsync(int page, int size)
    {
        var repository = _unitOfWork.GetRepository<Product, int>();
        return await repository.GetPagedAsync(page, size);
    }
}

4. Dynamic Filtering

var filter = new FilterModel
{
    SearchTerm = "laptop",
    Filters = new List<FilterItem>
    {
        new() { Field = "Price", Operator = "greaterthan", Value = "100" },
        new() { Field = "Name", Operator = "contains", Value = "gaming" }
    }
};

var products = await repository.GetPagedWithFilterAsync(filter, 1, 10);

5. Specification Pattern

public class ExpensiveProductsSpecification : BaseSpecification<Product>
{
    public ExpensiveProductsSpecification(decimal minPrice)
    {
        AddCriteria(p => p.Price >= minPrice);
        AddInclude(p => p.Category);
        ApplyOrderByDescending(p => p.Price);
    }
}

// Usage
var spec = new ExpensiveProductsSpecification(1000);
var expensiveProducts = await repository.GetAsync(spec);

6. Soft Delete with Global Query Filters

// In your DbContext's OnModelCreating method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    
    // Apply global query filters to exclude soft-deleted entities
    modelBuilder.ApplySoftDeleteQueryFilters();
}

// Usage examples:
// Normal queries automatically exclude soft-deleted entities
var activeProducts = await repository.GetAllAsync(); // Only non-deleted products

// Include soft-deleted entities when needed
var allProducts = await repository.GetQueryable()
    .IncludeDeleted()
    .ToListAsync();

// Get only soft-deleted entities
var deletedProducts = await repository.GetQueryable()
    .OnlyDeleted()
    .ToListAsync();

// Soft delete (sets IsDeleted = true, keeps data in database)
await repository.DeleteAsync(productId, saveChanges: true, isSoftDelete: true);

// Hard delete (actually removes from database)
await repository.DeleteAsync(productId, saveChanges: true, isSoftDelete: false);

IRepository<TEntity, TKey>

Core repository interface providing:

  • Basic CRUD operations
  • Advanced querying with includes and ordering
  • Pagination support
  • Bulk operations
  • Dynamic filtering

IUnitOfWork

Coordinates multiple repositories and provides:

  • Repository access
  • Transaction management
  • Change tracking
  • Bulk operations across repositories

BaseSpecification<T>

Flexible specification implementation supporting:

  • Complex criteria
  • Include expressions
  • Ordering
  • Pagination
  • Grouping

Base Classes

  • BaseEntity<TKey>: Simple entity with Id property
  • BaseAuditableEntity<TKey>: Entity with audit properties (CreatedAt, UpdatedAt, etc.)
  • ValueObject: Base class for value objects with equality comparison

Requirements

  • .NET 9.0 or later
  • Entity Framework Core 9.0.6 or later

Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

If you encounter any issues or have questions, please open an issue on our GitHub repository.

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 (2)

Showing the top 2 NuGet packages that depend on FS.EntityFramework.Library:

Package Downloads
FS.EntityFramework.Library.UlidGenerator

ULID ID generation extension for FS.EntityFramework.Library with full Domain-Driven Design (DDD) support. Provides chronologically sortable, human-readable unique identifiers perfect for enterprise microservice architectures, Aggregate Roots, and Domain Entities. Includes automatic generation, Entity Framework optimizations, and comprehensive DDD integration.

FS.EntityFramework.Library.GuidV7

GUID Version 7 (RFC 9562) ID generation extension for FS.EntityFramework.Library with comprehensive Domain-Driven Design (DDD) support. Provides timestamp-based sequential GUIDs with zero external dependencies, perfect for enterprise .NET 9+ applications requiring RFC-compliant, chronologically ordered unique identifiers for Aggregate Roots and Domain Entities.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
9.0.7.1 347 7/25/2025
9.0.7 196 7/19/2025
9.0.6.9 153 7/6/2025
9.0.6.8 136 7/6/2025
9.0.6.7 162 7/6/2025
9.0.6.6 141 6/30/2025
9.0.6.5 133 6/30/2025
9.0.6.1 315 6/24/2025

Initial release with Repository pattern, Unit of Work, and dynamic filtering support.