Phymnary.SugarPot.AspNetCore.EntityFrameworkCore 1.2.2

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

Phymnary.SugarPot.AspNetCore.EntityFrameworkCore

Entity Framework Core infrastructure for SugarPot applications.

This package provides:

  • Generic EF repositories
  • SaveChanges interceptors for auditing, soft delete, and tenant assignment
  • ModelBuilder helpers for table naming and global query filters
  • Transaction and resilient execution helpers

What Is Included

Repositories

  • EfRepository<TDbContext, TEntity>
  • EfRepository<TDbContext, TEntity, TKey>
  • Query/update customization via IRepositoryOptions<TEntity>:
    • EntityQueryOptions<TEntity>
    • EntityUpdateOptions<TEntity>

Interceptors

  • OnAttachedInterceptor (always registered by AddEfCoreServices)
  • SoftDeleteInterceptor (opt-in)
  • SetTenantOnSavingInterceptor (opt-in)
  • AuditOnSavingInterceptor (enabled through property-change audit registration)

Helpers

  • ModelBuilderHelper and BuildEntity(...)
  • IDbFunctionProvider implementation (DbFunctionProvider<TDbContext>)
  • IQueryTransaction wrapper (WrappedDbContextTransaction)

Target Frameworks And EF Core Versioning

This project targets:

  • net8.0
  • net9.0
  • net10.0

EF Core package version behavior in this project:

  • For net10.0-compatible targets: Microsoft.EntityFrameworkCore and Microsoft.EntityFrameworkCore.Relational use [10.0.0,)
  • Otherwise: the same packages use [8.0.0,)

Installation

dotnet add package Phymnary.SugarPot.AspNetCore.EntityFrameworkCore

Quick Start

1. Register SugarPot EF services

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Phymnary.SugarPot.AspNetCore.Extensions;

services.AddEfCoreServices<AppDbContext>(cfg =>
{
    cfg.AddSoftDelete();
    cfg.AddMultiTenancy();

    // Enables AuditOnSavingInterceptor and property-change tracking
    cfg.AddPropertyChangeAudit<AppDbContext, PropertyChangeAudit>(audit => new PropertyChangeAudit
    {
        EntityName = audit.EntityName,
        PropertyName = audit.PropertyName,
        TypeName = audit.TypeName,
        EntityId = audit.EntityId,
        OldValue = audit.OldValue,
        NewValue = audit.NewValue,
        ModifiedById = audit.ModifiedById,
        ModifiedAt = audit.ModifiedAt,
        IsDeleted = audit.IsDeleted,
    });
});

services.AddDbContext<AppDbContext>((sp, options) =>
{
    options.UseSqlServer(connectionString);

    // Add all registered EF interceptors
    options.AddInterceptors(sp.GetServices<IInterceptor>());
});

2. Inherit the repository base

using Phymnary.SugarPot.AspNetCore.Entities;
using Phymnary.SugarPot.AspNetCore.Repositories;

public sealed class UserRepository(
    AppDbContext dbContext,
    IRepositoryOptions<User> options,
    EfRepositoryAddons addons
) : EfRepository<AppDbContext, User, Guid>(dbContext, options, addons)
{
}

Common methods:

  • InsertAsync
  • UpsertAsync
  • UpdateAsync
  • FindAsync
  • QueryAsync
  • AnyAsync
  • CountAsync
  • AdvanceQuery(...)
  • Delete(...)
  • GetAsync(id) for keyed repositories

Repository Options

You can centralize entity behavior with IRepositoryOptions<TEntity>.

using Phymnary.SugarPot.AspNetCore.Repositories;

public sealed class UserRepositoryOptions : EfRepositoryOptions<User>
{
    public UserRepositoryOptions()
    {
        QueryOptions = new EntityQueryOptions<User>
        {
            DefaultIncludeQuery = q => q,
            IncludeDetailsQuery = q => q
                .IncludeIn(u => u.Profile)
        };

        UpdateOptions = new EntityUpdateOptions<User>
        {
            Update = (input, existing) =>
            {
                existing.Name = input.Name;
                existing.Email = input.Email;
            },
        };

        // Optional domain validator
        Validator = null;
    }
}

Notes:

  • UpsertAsync requires UpdateOptions.Update; otherwise it throws.
  • Delete(...) first executes UpdateOptions.OnDelete when provided.
  • If OnDelete returns true, default delete logic is skipped.

Advanced Query API

AdvanceQuery(...) supports ordering, paging, projection, and pagination metadata.

var page = await repository
    .AdvanceQuery(q => q.Where(x => x.IsActive))
    .OrderByDescending(x => x.CreatedAt)
    .Pick(perPage: 20, pageIndex: 1)
    .PaginateAsync(ct);

PaginateAsync returns:

  • Count: total item count for the base filtered query
  • Items: paged IAsyncEnumerable<T>

ModelBuilder Helper

Use ModelBuilderHelper to keep entity mapping consistent.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    var helper = new ModelBuilderHelper(modelBuilder)
    {
        TenantIdAccessor = () => _currentTenant.Id!.Value,
    };

    helper
        .BuildEntity<User>(schema: "app")
        .BuildEntity<Order>(schema: "app");
}

Behavior:

  • Table name defaults to CLR type name
  • Applies soft-delete filter for entities implementing ISoftDelete
  • Applies tenant filter for entities implementing IMultiTenant
    • On net10.0+, tenant accessor is required for multi-tenant entities

Runtime Dependencies

When enabling features, make sure these services are available in DI from your application/domain layer:

  • ICurrentUser
  • IRunAt
  • IAbortedToken
  • ICurrentTenant (required when multi-tenancy is enabled)

Notes

  • OnAttachedInterceptor is always added by AddEfCoreServices.
  • AuditOnSavingInterceptor is registered when AddPropertyChangeAudit(...) is configured.
  • ConfigureAuditing(...) currently stores internal metadata used by this package.

License

See the repository root for license details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.2.2 85 9/18/2026
1.2.1 141 7/27/2026
1.2.0 219 6/15/2026
1.1.0 133 6/7/2026
1.0.0 142 6/5/2026