RootBlocks 0.8.0
See the version list below for details.
dotnet add package RootBlocks --version 0.8.0
NuGet\Install-Package RootBlocks -Version 0.8.0
<PackageReference Include="RootBlocks" Version="0.8.0" />
<PackageVersion Include="RootBlocks" Version="0.8.0" />
<PackageReference Include="RootBlocks" />
paket add RootBlocks --version 0.8.0
#r "nuget: RootBlocks, 0.8.0"
#:package RootBlocks@0.8.0
#addin nuget:?package=RootBlocks&version=0.8.0
#tool nuget:?package=RootBlocks&version=0.8.0
RootBlocks
RootBlocks is a set of .NET packages that provide the building blocks of Domain-Driven Design (DDD). It covers entities, aggregate roots, value objects, enumeration classes, domain events, a unit of work with a transactional outbox, and persistence helpers for Entity Framework Core and raw SQL. You write the business rules and RootBlocks handles the repetitive parts.
public class Post : Entity< PostId >, IAggregateRoot
{
public string Title { get; private set; }
public DateTime? PublishedOn { get; private set; }
public Post( string title ) : base( PostId.New() ) => Title = title;
public void Publish()
{
PublishedOn = DateTime.UtcNow;
AddDomainEvent( new PostPublished( Id ) );
}
}
// In a command handler
var post = await posts.GetByIdAsync( postId, cancellationToken );
post.Publish();
unitOfWork.RegisterDirty( post );
await unitOfWork.CommitAsync( cancellationToken ); // saves the post and PostPublished together, then publishes it
Features
- Domain model:
Entity<T>with domain events and audit dates,IAggregateRoot,ValueObjectwith structural equality,Enumerationclasses,DomainEventwith causation and correlation IDs, and domain exceptions. - Unit of work for EF Core: commits aggregates, collects their domain events, and checks optimistic concurrency with a
RowVersion. - Transactional outbox: events are saved in the same transaction as the change, published straight after, and retried with exponential backoff by a background dispatcher. One outbox per context, so each module of a modular monolith has its own. Plain SQL only: no Service Broker, so it runs on Azure SQL and in containers.
- Soft delete, UTC dates and auditing handled by the base
DbContextand entity configurations. - CQRS read side: an
IConnectionFactoryfor Dapper or ADO.NET, with drivers for SQL Server, PostgreSQL, MySQL, Oracle and SQLite. - Integrations: MediatR for in-process events, Serilog for log context, and transformers for the built-in ASP.NET Core OpenAPI document.
Packages
| Package | Target | What it gives you |
|---|---|---|
RootBlocks |
netstandard2.1 |
Core DDD types (Entity<T>, IAggregateRoot, ValueObject, Enumeration, DomainEvent), repository and unit-of-work abstractions, pagination, exceptions and small helpers. Every other package depends on it. |
RootBlocks.Persistence.EntityFramework |
net10.0 |
EF Core base DbContext, entity configurations, UnitOfWork, soft delete, optimistic concurrency and the transactional outbox. |
RootBlocks.Persistence |
netstandard2.1 |
An IConnectionFactory for raw ADO.NET or Dapper queries (the read side of CQRS). Use it with one of the drivers below. |
RootBlocks.Persistence.SqlClient |
netstandard2.1 |
SQL Server driver (Microsoft.Data.SqlClient). |
RootBlocks.Persistence.Npgsql |
net10.0 |
PostgreSQL driver (Npgsql). |
RootBlocks.Persistence.MySqlClient |
netstandard2.1 |
MySQL driver (MySql.Data). |
RootBlocks.Persistence.Oracle |
netstandard2.1 |
Oracle driver (Oracle.ManagedDataAccess.Client, from CYQ.Data.Oracle). |
RootBlocks.Persistence.SQLite |
netstandard2.1 |
SQLite driver (System.Data.SQLite). |
RootBlocks.Messaging.MediatR |
net10.0 |
An IEventPublisher that dispatches domain events through MediatR. |
RootBlocks.Serialization |
net10.0 |
A System.Text.Json converter that round-trips domain events, private setters included. |
RootBlocks.Serialization.Newtonsoft.Json |
net10.0 |
The Newtonsoft JSON Patch input formatter for MVC apps. Minimal APIs do not need it. |
RootBlocks.Logging.Serilog |
net10.0 |
A Serilog implementation of ILogContext, plus a preset logging setup for apps that have no appsettings.json. |
RootBlocks.AspNetCore.OpenApi |
net10.0 |
Transformers for the built-in Microsoft.AspNetCore.OpenApi document, such as JSON Patch examples. Works with any UI. |
See Target frameworks for what each target means for your project.
Installation
Install the packages you need from NuGet:
dotnet add package RootBlocks
dotnet add package RootBlocks.Persistence.EntityFramework
dotnet add package RootBlocks.Messaging.MediatR
dotnet add package RootBlocks.Persistence.SqlClient # or .Npgsql, .MySqlClient, .Oracle, .SQLite
RootBlocks does not ship an identifier type. Entity<T> accepts any T : IEquatable<T>, such as Guid, int or string. For strongly-typed IDs like PostId, use the separate StronglyTypedIdentifier library, which also provides the EF Core and ASP.NET Core integration for those IDs. The examples in these docs use it.
Then wire it up in your composition root:
builder.Services
.AddMediatR( cfg => cfg.RegisterServicesFromAssembly( typeof( PublishPostCommand ).Assembly ) )
.AddMessaging() // IEventPublisher through MediatR
.AddSqlClientPersistence( connectionString ) // IConnectionFactory for queries
.AddDbContext< Context >( o => o.UseSqlServer( connectionString ) )
.AddOutbox< Context >( builder.Configuration ) // when the context calls modelBuilder.ApplyOutbox()
.AddScoped< IUnitOfWork, UnitOfWork >()
.AddScoped< IPostRepository, PostRepository >();
Getting started builds this up step by step.
Upgrading from 0.5
Version 0.6 rewrote the outbox: it is now per context, retried, and free of Service Broker. The old API still compiles with obsolete warnings. See Upgrading to 0.6 for the migration.
Documentation
- Getting started: build a working aggregate, from the domain model to the API, step by step.
- Core library
- Domain model: entities, aggregate roots, value objects, enumerations, domain events and domain exceptions.
- Utilities: pagination, extension methods, validation, retry and the other abstractions.
- Packages
- Entity Framework persistence:
DatabaseContext, configurations,UnitOfWorkand the outbox. - Connection factory and database drivers
- Messaging with MediatR
- Serialization
- Logging with Serilog
- OpenAPI
- Entity Framework persistence:
- Configuration reference: every registration method and setting in one place.
- Upgrading to 0.6
- Target frameworks
- The Blogs sample: a full reference application.
- Contributing: building, testing, versioning and releasing.
Sample
samples/Blogs is a minimal API that uses every package together. It has three aggregates (Person, Blog, Post), MediatR commands, EF Core with the outbox for writes and Dapper for reads, and a Scalar UI over the OpenAPI document. See the sample guide.
dotnet run --project samples/Blogs/src/Blogs.Api/
Building from source
dotnet build RootBlocks.slnx
dotnet test # the EF tests need Docker for SQL Server
The SDK is pinned in global.json. See Contributing for conventions, versioning and releases.
License
MIT © Sébastien de Salvador
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- MediatR.Contracts (>= 2.0.1)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on RootBlocks:
| Package | Downloads |
|---|---|
|
RootBlocks.AspNetCore.Swashbuckle
Provides Filters to render certain objects from the RootBlocks library correctly in Swagger. |
|
|
RootBlocks.Serialization
Utilities and extensions for enhanced serialization in the RootBlocks library. |
|
|
RootBlocks.Messaging.MediatR
Provides a MediatR implementation of the IEventPublisher from the RootBlocks library, mainly used to dispatch events internally. |
|
|
RootBlocks.Logging.Serilog
Provides a Serilog implementation of the ILogContext from the RootBlocks library + a couple of easy to use Add methods to add easily add Serilog to projects without appsettings.json like Azure Functions. |
|
|
RootBlocks.Serialization.Newtonsoft.Json
Helper to add support for JSON Patch requests which currently not supported by System.Text.Json. |
GitHub repositories
This package is not used by any popular GitHub repositories.