Trellis.EntityFrameworkCore 3.0.0-alpha.505

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

Trellis.EntityFrameworkCore

NuGet Package

EF Core conventions and helpers for Trellis value objects, Maybe<T>, and Result-based persistence.

Installation

dotnet add package Trellis.EntityFrameworkCore

Quick Example

using Microsoft.EntityFrameworkCore;
using Trellis;
using Trellis.EntityFrameworkCore;

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) =>
    configurationBuilder.ApplyTrellisConventions(typeof(AppDbContext).Assembly);

// Reflection-free alternative — generated at compile time, no assembly scan:
//   configurationBuilder.ApplyTrellisConventionsFor<AppDbContext>();

Maybe<Customer> customer = await dbContext.Customers.FirstOrDefaultMaybeAsync(cancellationToken);
Result<int> saved = await dbContext.SaveChangesResultAsync(cancellationToken);

Key Features

  • Commit ownership: EfUnitOfWork.BeginScope() returns IUnitOfWorkScope; IsOwner is true only for the outer scope. Nested commands defer persistence and event dispatch until the owning command succeeds; DTO/Unit outer responses retain nested aggregate events. Automatic event dispatch under a manually owned outer scope is rejected; use explicit post-commit dispatch instead.
  • Apply Trellis value converters and owned-type conventions with one registration point.
  • Owned-collection (OwnsMany) children that declare their own primary key are treated as domain-assigned: the key is marked ValueGenerated.Never, so an application-supplied Guid/long/int key persists on every provider (no SQL Server IDENTITY 544 error, no spurious 409 when adding a child to an already-loaded parent). Opt back into store generation with an explicit ValueGeneratedOnAdd() or [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
  • Query Maybe<T> naturally instead of dropping to storage-specific null handling.
  • Return Result<int> or Result from save operations instead of throwing on expected failures.
  • Idempotent inserts on a unique constraint via db.TryInsertUniqueAsync(entity, ct) — duplicate-key violations surface as a failed Result<TEntity> carrying an Error.Conflict with reason code "duplicate.key" and the provider-extracted ConstraintName / ConstraintTableName telemetry fields, so worker outboxes and "save unless exists" deduplication never throw on redelivery.
  • Typed cursor pagination via IQueryable<T>.ToPageAsync(request, seek, …) — SeekDefinition keeps single/composite, ascending/descending ordering and seek predicates together; malformed client state returns Error.InvalidInput.
  • RepositoryBase<TAggregate, TId> — staging-only base class (Add/Remove/Query/Exists/Count).
  • IUnitOfWork / EfUnitOfWork<TContext> — single commit boundary for staged changes.
  • TransactionalCommandBehavior — Mediator pipeline behavior that auto-commits after successful command handlers (requires Mediator pipeline registration). Also commits on Result.FailAfterCommit<T>(error) outcomes so persist-on-failure handlers (e.g., a worker recording a permanent-failure transition) can stage state alongside the failed result.

Typed predicates over optional values

var overdue = await dbContext.Orders
    .WhereHasValue(o => o.SubmittedAt, value => value < cutoff)
    .ToListAsync(cancellationToken);

Breaking change: WhereLessThan, WhereLessThanOrEqual, WhereGreaterThan, and WhereGreaterThanOrEqual are replaced by WhereHasValue(selector, predicate). Move <, <=, >, or >= into the value lambda. The overload accepts an Expression<Func<TInner, bool>>, including reusable expression variables, not a compiled delegate. Absent values are always excluded, even for a constant-true predicate. Presence-only WhereHasValue(selector), equality, and ordering helpers are unchanged.

C# checks the predicate's operators; the configured provider must translate them. String/GUID ordering follows provider semantics, and unsupported translations (such as DateTimeOffset relational comparisons on SQLite) throw without a client-side fallback. The helper targets storage directly; scalar value-object .Value access still requires AddTrellisInterceptors(). For shared domain specifications, continue using Maybe<T>.HasValueWhere with an inline lambda and AddTrellisInterceptors() for EF execution.

Typed seek pagination

var seek = SeekDefinition.Descending<Order, DateTimeOffset>(o => o.CreatedAt)
    .ThenAscending(o => o.Id.Value);

Result<Page<Order>> page = await PageRequest.TryCreate(cursor, limit)
    .BindAsync(request => authorizedOrders.AsNoTracking()
        .ToPageAsync(request, seek, cancellationToken: ct));

Supply an authorized, pre-filtered IQueryable<Order>. PageRequest distinguishes missing input from invalid empty cursors/non-positive limits; above-cap limits clamp by default (PageSizeLimitPolicy.Reject opts into rejection). The helper decodes typed state, seeks before Take(Applied + 1), and assembles a forward page. Boundary values are projected with the database query using the same key expressions, not recomputed in C# after materialization. Provider-translated functions are supported when the provider translates the complete query.

End with a stable unique key. Null keys are unsupported; verify your provider's translation and comparison/collation semantics. .Id.Value projection requires AddTrellisInterceptors(). There is no client-side fallback or snapshot guarantee, and descending traversal is not previous-page support. Cancellation and provider failures propagate rather than becoming malformed-cursor errors.

Use explicit key codecs or seek.WithCodec(...) for custom/context-bound/protected state. Built-ins are versioned and unsigned; old unversioned tokens are rejected. The single-key ascending ToPageAsync(pageSize, cursor, keySelector, …) convenience remains. For non-translatable computed ordering, use an explicitly bounded application algorithm with Core codecs and PageBuilder instead.

Documentation

Part of Trellis

This package is part of the Trellis framework.

Product Compatible and additional computed target framework versions.
.NET 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 (3)

Showing the top 3 NuGet packages that depend on Trellis.EntityFrameworkCore:

Package Downloads
Trellis.ServiceDefaults

Opinionated service composition defaults for Trellis web services. Provides a tiered builder that wires ASP integration, Mediator behaviors, FluentValidation, resource authorization, actor providers, and EF Core Unit of Work in canonical order.

Trellis.EntityFrameworkCore.Outbox

Transactional outbox for Trellis. Atomically captures aggregate domain events to an EF Core table in the same transaction as the aggregate change, then relays them to Trellis domain-event handlers — durable, at-least-once, in-process dispatch.

Trellis.EntityFrameworkCore.Inbox

Transactional inbox for Trellis — the consume-side complement to the outbox. Makes integration-event consumption idempotent: redeliveries of the same message are deduplicated by message id within the consumer's unit of work, so a handler's side effects commit exactly once. EF Core reference store.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0-alpha.527 0 10/1/2026
3.0.0-alpha.526 30 9/30/2026
3.0.0-alpha.524 62 9/27/2026
3.0.0-alpha.520 78 9/25/2026
3.0.0-alpha.516 171 9/22/2026
3.0.0-alpha.513 74 9/22/2026
3.0.0-alpha.505 197 9/13/2026
3.0.0-alpha.495 245 8/24/2026
3.0.0-alpha.458 195 8/19/2026
3.0.0-alpha.455 140 8/19/2026
3.0.0-alpha.449 91 8/18/2026
3.0.0-alpha.447 86 8/18/2026
3.0.0-alpha.432 126 7/6/2026
3.0.0-alpha.428 137 7/3/2026
3.0.0-alpha.425 156 6/27/2026
3.0.0-alpha.419 103 6/24/2026
3.0.0-alpha.418 188 6/23/2026
3.0.0-alpha.417 88 6/23/2026
3.0.0-alpha.397 92 6/18/2026
3.0.0-alpha.396 92 6/18/2026
Loading failed