Eternet.Crud.Relational
3.1.9
Prefix Reserved
See the version list below for details.
dotnet add package Eternet.Crud.Relational --version 3.1.9
NuGet\Install-Package Eternet.Crud.Relational -Version 3.1.9
<PackageReference Include="Eternet.Crud.Relational" Version="3.1.9" />
<PackageVersion Include="Eternet.Crud.Relational" Version="3.1.9" />
<PackageReference Include="Eternet.Crud.Relational" />
paket add Eternet.Crud.Relational --version 3.1.9
#r "nuget: Eternet.Crud.Relational, 3.1.9"
#:package Eternet.Crud.Relational@3.1.9
#addin nuget:?package=Eternet.Crud.Relational&version=3.1.9
#tool nuget:?package=Eternet.Crud.Relational&version=3.1.9
Eternet.Crud.Relational
Relational CRUD runtime, generated relational bridge conventions, bulk primitives, and relational outbox support for
Eternet.Mediator.
Installation
dotnet add package Eternet.Crud.Relational
Current Package Shape
As of April 2026, the supported authoring model is:
- request-first relational CRUD, where the public contract stays on the contracts/public handler and the internal relational request becomes the semantic source of truth
- aggregate-root semantics for single-entity create, update, delete, and upsert lanes
- first-class homogeneous bulk create, bulk delete, and bulk update lanes
- generated relational bridges that bind deterministic request/runtime inputs and publish reserved downstream outputs
- explicit
IDomainEventplus relational outbox projection as the default outbox model - legacy
CreateEntityCommand<Response>/UpdateEntityCommand<Response>/DeleteEntityCommand<Response>and[HandlerForEntity<TEntity>]only as compatibility paths
The modern relational lane is centered on a single explicit relational request type:
public sealed partial class UpdateJournalEntryHandler :
UpdateJournalEntry,
IRelationalUpdateImplementation<UpdateJournalEntryRelational.Request>
{
public override Response Handle(Request request) => request.StepsResults!.Response!;
}
public static partial class UpdateJournalEntryRelational
{
public sealed partial record Request
: RelationalUpdateEntityCommand<AccountingContext, JournalEntry, int>
{
public override int GetKey() => Id;
}
}
For update work, the internal relational request above is the supported replacement for authoring new features on
UpdateEntityCommand<Response>.
Recent Changes
The last two weeks materially changed both Eternet.Crud.Relational and Eternet.Crud.Relational.Generator:
- bulk delete, bulk create, and bulk update are now first-class relational lanes instead of bespoke custom-write patterns
- relational CRUD moved to the request-first API where
IRelational*Implementation<TRelationalRequest>declares one explicit internal relational request type - create/update/delete/upsert semantics are documented and enforced at the aggregate-root boundary
- generated bridge steps now return
StepResult<T>and preserve compatible custom relational result types for single-entity lanes GeneratedPipelineRuntimeis no longer the public runtime anchor for generated bridge glue; generated code now stays behind assembly-local helpers backed byGeneratedBindingRuntime- relational outbox authoring now defaults to explicit
IDomainEventemission plus registered projector translation; the old legacy outbox compatibility APIs were removed - generated bridge policy is emitted as assembly metadata so test/runtime discovery can reason about handlers across files and referenced assemblies
- nested relational handlers now get deterministic unique bridge artifact names
[RelationalEntityBinding("Alias")]can publish an additional downstream alias for the aggregate entity while keeping the defaultEntityoutput- scalar binding in generated bridges was tightened so request members bind deterministically by member name and type
Preferred Authoring Model
For new relational features:
- Keep the public request/contract in the contracts or public server layer and express API semantics with
IEndpointCreate,IEndpointUpdate,IEndpointDelete,IEndpointUpsert, or the relevant query contract. - Keep the public handler on that contract and implement one of the
IRelationalCreate/Update/Delete/UpsertImplementation<TRelationalRequest>interfaces. - Declare an app-owned internal relational request that inherits the appropriate relational request base:
RelationalCreateEntityCommand<...>,RelationalUpdateEntityCommand<...>,RelationalDeleteEntityCommand<...>, orRelationalUpsertEntityCommand<...>. - Let
Eternet.Crud.Relational.Generatoraugment that request, generate the bridge, and publish the reserved downstream outputs. - Keep domain materialization/mutation and
IDomainEventemission in the app-owned relational business handler or pipeline steps.
For homogeneous set writes, keep the same request-first model and switch the internal relational request to one of the bulk bases:
RelationalBulkCreateCommand<...>RelationalBulkDeleteCommand<...>RelationalBulkUpdateCommand<...>
Compatibility And Roadmap
Legacy relational surfaces still compile, but they are no longer the design target for new code:
[HandlerForEntity<TEntity>]remains compatibility-onlyCreateEntityCommand<Response>,UpdateEntityCommand<Response>, andDeleteEntityCommand<Response>remain compatibility-onlyConfigureGeneratedRelationalCommand(...)remains deprecated migration scaffolding- legacy
*RelationalHooksare already unsupported Eternet.Crud.Relational.Generatordiscovers the relational key path from deterministic EF metadata and explicit relational contracts instead of naming heuristics (Id,<EntityName>Id,[Key]) orIIntIdentity/IStringIdentity; the remaining cleanup is the runtime/public-surface identity coupling
The relational identity decoupling work is tracked in
docs/plans/relational/identity-decoupling-plan.md:
remove nondeterministic key and lookup heuristics from the relational lane(done)- stop treating
IIntIdentityandIStringIdentityas part of the modern relational authoring model - decouple the modern relational lane from
IIdentity - obsolete legacy relational authoring entry points and back that stance with analyzer diagnostics and migration guidance
That future wave is intentionally scoped to Crud.Relational first; it does not require broad immediate cleanup across
all of Eternet.Mediator.
Related Docs
docs/README.mdfor the organized documentation indexdocs/guides/behaviors.mdfor the current runtime model, bridge conventions, compatibility notes, and examplesdocs/guides/bulk-operations.mdfor lane selection and bulk primitive guidancedocs/guides/outbox.mdfor the explicit relational outbox modeldocs/guides/include-configuration.mdfor legacy include configuration and the modern eager-loading alternativedocs/plans/relational/identity-decoupling-plan.mdfor the next cleanup wave
Migration Note: ScopedStates Retirement
Eternet.Crud.Relational 3.0.0 aligned with the ScopedStates retirement in Eternet.Mediator.
GeneratedRelationalCommandBinderno longer depends on a publicScopedStatesservice or constructor argument.- Relational bridge binding now resolves values through
GeneratedBindingRuntimeand the ambient generated runtime scope. - Tests or custom infrastructure that previously created
ScopedStatesmanually should migrate toGeneratedBindingRuntime.EnterScope()andGeneratedBindingRuntime.Publish(...)when they need runtime state in-process.
Migration guide:
../../Eternet.Mediator/docs/scoped-states-breaking-change-v3.md
| Product | Versions 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 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. |
-
net10.0
- Eternet.Mediator (>= 3.0.3)
- Microsoft.EntityFrameworkCore (>= 10.0.5)
- Microsoft.Extensions.DependencyInjection (>= 10.0.5)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.5)
- Microsoft.Extensions.Hosting (>= 10.0.5)
- Microsoft.Extensions.Logging (>= 10.0.5)
-
net9.0
- Eternet.Mediator (>= 3.0.3)
- Microsoft.EntityFrameworkCore (>= 9.0.10)
- Microsoft.Extensions.DependencyInjection (>= 9.0.10)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 9.0.10)
- Microsoft.Extensions.Hosting (>= 9.0.10)
- Microsoft.Extensions.Logging (>= 9.0.10)
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 |
|---|---|---|
| 3.1.30 | 50 | 5/27/2026 |
| 3.1.29 | 91 | 5/26/2026 |
| 3.1.28 | 111 | 5/21/2026 |
| 3.1.27 | 89 | 5/20/2026 |
| 3.1.26 | 89 | 5/20/2026 |
| 3.1.25 | 88 | 5/20/2026 |
| 3.1.24 | 116 | 5/19/2026 |
| 3.1.23 | 100 | 5/18/2026 |
| 3.1.22 | 119 | 5/14/2026 |
| 3.1.21 | 97 | 5/11/2026 |
| 3.1.20 | 118 | 5/8/2026 |
| 3.1.19 | 133 | 5/5/2026 |
| 3.1.18 | 106 | 5/4/2026 |
| 3.1.17 | 103 | 5/1/2026 |
| 3.1.16 | 91 | 5/1/2026 |
| 3.1.15 | 94 | 5/1/2026 |
| 3.1.14 | 92 | 5/1/2026 |
| 3.1.13 | 93 | 4/30/2026 |
| 3.1.12 | 150 | 4/23/2026 |
| 3.1.9 | 127 | 4/13/2026 |
Aggregate-root lane semantics: create makes new roots; update handles root-governed child mutations.