Async/await first CQRS+ES and DDD framework for .NET
EventFlow
and EventFlow.EntityFramework
packagesAggregateRoot<,>
virtual
to allow
easier customization -- query before the fix
UPDATE [ReadModel-TestAttributes]
SET UpdatedTime = @UpdatedTime
WHERE Id = @Id
-- query after the fix
UPDATE [ReadModel-TestAttributes]
SET [UpdatedTime] = @UpdatedTime
WHERE [Id] = @Id
null
predicate to AddCommands
and AddJobs
EventFlow.AspNetCore
NuGet package now has ASP.NET Core 3 supportMongoDbReadModelStore readModelStore;
IQueryable<TReadModel> queryable = readModelStore.AsQueryable();
RabbitMqPublisher
to a new virtual
method to ease reuse and customizationnew()
generic requirement,
which aligns read model requirements with the rest of EventFlow"null"
into a struct value like
int
, the SingleValueObjectConverter
threw an exception instead of
merely returning null
representing an absent SingleValueObject<int>
valueAspNetCoreEventFlowOptions.AddMetadataProviders()
to AddDefaultMetadataProviders()
and made AddUserClaimsMetadata
opt-in
in order to prevent policy issues.IEmit<>
in aggregate roots.AddAspNetCore()
with defaults now doesn't throw a DI
exception.EventFlowOptions.New.
.ConfigureJson(json => json
.AddSingleValueObjects()
.AddConverter<SomeConverter>()
)
services.AddEventFlow(o => o.AddAspNetCore(c => {...}));
(old syntax
AddAspNetCoreMetadataProviders
is now deprecated)..RunBootstrapperOnHostStartup()
runs bootstrappers together with ASP.NET
host startup. Previously, this was done in AddAspNetCoreMetadataProviders
and led to some confusion..UseMvcJsonOptions()
adds EventFlow JSON configuration (see below) to ASP.NET Core,
so you can accept and return Single Value Objects as plain strings for example..Add{Whatever}Metadata()
configures specific metadata provider..AddUserClaimsMetadata(params string claimTypes)
configures the new claims metadata
provider (for auditing or "ChangedBy" in read models)..UseLogging()
configures an adapter for Microsoft.Extensions.Logging.UseModelBinding()
adds model binding support for Single Value Objects:
[HttpGet("customers/{id}")]
public async Task<IActionResult> SingleValue(CustomerId id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
AddRequestHeadersMetadataProvider
doesn't throw when
HttpContext is null.ReadModelRepopulator
now correctly populates IAmAsyncReadModelFor
EventFlow.TestHelpers
are now released as .NET Standard as wellEventStore.Client
to v5.0.1 and use it for both .NET Framework and .NET CoreMsSqlEventPersistence
now correctly
handles non-ANSI unicode characters in strings.false
in IExecutionResult.IsSuccess
will newly lead to an exception being thrown.
For disabling all new changes just set protected property
AggregateSaga.ThrowExceptionsOnFailedPublish
to false
in your AggregateSaga constructor.
Also an Exception thrown from any command won't prevent other commands from being executed.
All exceptions will be collected and then re-thrown in SagaPublishException (even in case
of just one Exception). The exception structure is following:
false
in IExecutionResult.IsSuccess
You need to update your ISagaErrorHandler
implementation to reflect new exception structure,
unless you disable this new feature.options.Configure(c => c.CancellationBoundary = CancellationBoundary.BeforeCommittingEvents)
EventFlowOptions.RunOnStartup<TBootstrap>
extension method to
register IBootstrap
types that should run on application startup.IAmAsyncReadModelFor
).
You can mix and match asynchronous and synchronous updates,
as long as you don't subscribe to the same event in both ways.dbo
to the eventdatamodel_list_type
in script
0002 - Create eventdatamodel_list_type.sql
for EventFlow.MsSql
.LoadAllCommittedEvents
now correctly handles cases where the
GlobalSequenceNumber
column contains gaps larger than the page size. This bug
lead to incomplete event application when using the ReadModelPopulator
(see #564).IResolver.Resolve<T>()
and IResolver.Resolve(Type)
now throw an
exception for unregistered services when using EventFlow.DependencyInjection
.ValidateRegistrations
when decorator
components are co-located together with other components that are registed using
Add*
-methods