Projection With FromAll
FromAll is a .NET declarative projection API that maps properties from every event considered by the projection, excluding child projection events by default. Other clients expose the same underlying concept through their every-event APIs configured to exclude children; see Projection With FromEvery for the full every-event feature set.
Use FromAll in .NET when the projection should express that a mapping belongs to the all-events portion of the projection definition. In Elixir, the same default (excluding child projection events) is what from_every does when :include_children is omitted. In TypeScript, call excludeChildProjections() on the fromEvery builder to get the same behavior.
Basic Usage
Section titled “Basic Usage”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record UserCreatedDeclarativeAll(string Name, string Email);
[EventType]public record UserEmailChangedDeclarativeAll(string Email);
public record UserProfileDeclarativeAll( string Name, string Email, DateTimeOffset LastUpdated);
public class UserProfileDeclarativeAllProjection : IProjectionFor<UserProfileDeclarativeAll>{ public void Define(IProjectionBuilderFor<UserProfileDeclarativeAll> builder) => builder .From<UserCreatedDeclarativeAll>() .From<UserEmailChangedDeclarativeAll>() .FromAll(_ => _ .Set(m => m.LastUpdated) .ToEventContextProperty(c => c.Occurred));}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.UserCreatedDeclarativeAll do use Chronicle.Events.EventType, id: "user-created-declarative-all-v1"
defstruct [:name, :email]end
defmodule MyApp.Events.UserEmailChangedDeclarativeAll do use Chronicle.Events.EventType, id: "user-email-changed-declarative-all-v1"
defstruct [:email]end
defmodule MyApp.ReadModels.UserProfileDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:name, :email, :last_updated]end
defmodule MyApp.Projections.UserProfileDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.UserProfileDeclarativeAll
alias MyApp.Events.{UserCreatedDeclarativeAll, UserEmailChangedDeclarativeAll}
from UserCreatedDeclarativeAll from UserEmailChangedDeclarativeAll
from_every set: [last_updated: :occurred]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class UserCreatedDeclarativeAll { constructor(readonly name: string, readonly email: string) {}}
@eventType()class UserEmailChangedDeclarativeAll { constructor(readonly email: string) {}}
@readModel()class UserProfileDeclarativeAll { name = ''; email = ''; lastUpdated = new Date();}
@projection('', UserProfileDeclarativeAll)class UserProfileDeclarativeAllProjection implements IProjectionFor<UserProfileDeclarativeAll> { define(builder: IProjectionBuilderFor<UserProfileDeclarativeAll>): void { builder .from(UserCreatedDeclarativeAll) .from(UserEmailChangedDeclarativeAll) .fromEvery(_ => _ .set(m => m.lastUpdated) .toEventContextProperty('occurred') .excludeChildProjections()); }}Event Context Fields
Section titled “Event Context Fields”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountTouchedDeclarativeAll(string Reason);
public record AccountAuditDeclarativeAll( DateTimeOffset LastUpdated, EventSequenceNumber LastEventSequence, string LastCorrelationId);
public class AccountAuditDeclarativeAllProjection : IProjectionFor<AccountAuditDeclarativeAll>{ public void Define(IProjectionBuilderFor<AccountAuditDeclarativeAll> builder) => builder .From<AccountTouchedDeclarativeAll>() .FromAll(_ => _ .Set(m => m.LastUpdated).ToEventContextProperty(c => c.Occurred) .Set(m => m.LastEventSequence).ToEventContextProperty(c => c.SequenceNumber) .Set(m => m.LastCorrelationId).ToEventContextProperty(c => c.CorrelationId));}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.AccountTouchedDeclarativeAll do use Chronicle.Events.EventType, id: "account-touched-declarative-all-v1"
defstruct [:reason]end
defmodule MyApp.ReadModels.AccountAuditDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:last_updated, :last_event_sequence, :last_correlation_id]end
defmodule MyApp.Projections.AccountAuditDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountAuditDeclarativeAll
alias MyApp.Events.AccountTouchedDeclarativeAll
from AccountTouchedDeclarativeAll
from_every set: [ last_updated: :occurred, last_event_sequence: "$context.sequenceNumber", last_correlation_id: "$context.correlationId" ]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class AccountTouchedDeclarativeAll { constructor(readonly reason: string) {}}
@readModel()class AccountAuditDeclarativeAll { lastUpdated = new Date(); lastEventSequence = 0n; lastCorrelationId = '';}
@projection('', AccountAuditDeclarativeAll)class AccountAuditDeclarativeAllProjection implements IProjectionFor<AccountAuditDeclarativeAll> { define(builder: IProjectionBuilderFor<AccountAuditDeclarativeAll>): void { builder .from(AccountTouchedDeclarativeAll) .fromEvery(_ => _ .set(m => m.lastUpdated).toEventContextProperty('occurred') .set(m => m.lastEventSequence).toEventContextProperty('sequenceNumber') .set(m => m.lastCorrelationId).toEventContextProperty('correlationId') .excludeChildProjections()); }}Event Source Id
Section titled “Event Source Id”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountOpenedDeclarativeAll(string OwnerName);
public record AccountSummaryDeclarativeAll( string AccountId, string OwnerName);
public class AccountSummaryDeclarativeAllProjection : IProjectionFor<AccountSummaryDeclarativeAll>{ public void Define(IProjectionBuilderFor<AccountSummaryDeclarativeAll> builder) => builder .From<AccountOpenedDeclarativeAll>() .FromAll(_ => _ .Set(m => m.AccountId) .ToEventSourceId());}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.AccountOpenedDeclarativeAll do use Chronicle.Events.EventType, id: "account-opened-declarative-all-v1"
defstruct [:owner_name]end
defmodule MyApp.ReadModels.AccountSummaryDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:account_id, :owner_name]end
defmodule MyApp.Projections.AccountSummaryDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountSummaryDeclarativeAll
alias MyApp.Events.AccountOpenedDeclarativeAll
from AccountOpenedDeclarativeAll
from_every set: [account_id: :event_source_id]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class AccountOpenedDeclarativeAll { constructor(readonly ownerName: string) {}}
@readModel()class AccountSummaryDeclarativeAll { accountId = ''; ownerName = '';}
@projection('', AccountSummaryDeclarativeAll)class AccountSummaryDeclarativeAllProjection implements IProjectionFor<AccountSummaryDeclarativeAll> { define(builder: IProjectionBuilderFor<AccountSummaryDeclarativeAll>): void { builder .from(AccountOpenedDeclarativeAll) .fromEvery(_ => _ .set(m => m.accountId) .toEventSourceId() .excludeChildProjections()); }}With Event-Specific Mappings
Section titled “With Event-Specific Mappings”FromAll can sit beside event-specific From mappings. Use event-specific mappings for business state, and reserve FromAll for metadata that should update for every projected event.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record OrderCreatedDeclarativeAll(string OrderNumber);
[EventType]public record OrderShippedDeclarativeAll(string TrackingNumber);
public record OrderDeclarativeAll( string OrderNumber, string Status, DateTimeOffset LastModified);
public class OrderDeclarativeAllProjection : IProjectionFor<OrderDeclarativeAll>{ public void Define(IProjectionBuilderFor<OrderDeclarativeAll> builder) => builder .FromAll(_ => _ .Set(m => m.LastModified) .ToEventContextProperty(c => c.Occurred)) .From<OrderCreatedDeclarativeAll>(_ => _ .Set(m => m.Status) .ToValue("Placed")) .From<OrderShippedDeclarativeAll>(_ => _ .Set(m => m.Status) .ToValue("Shipped"));}Kotlin does not support this workflow yet.Java does not support this workflow yet.Elixir does not support this workflow yet.import { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class OrderCreatedDeclarativeAll { constructor(readonly orderNumber: string) {}}
@eventType()class OrderShippedDeclarativeAll { constructor(readonly trackingNumber: string) {}}
@readModel()class OrderDeclarativeAll { orderNumber = ''; status = ''; lastModified = new Date();}
@projection('', OrderDeclarativeAll)class OrderDeclarativeAllProjection implements IProjectionFor<OrderDeclarativeAll> { define(builder: IProjectionBuilderFor<OrderDeclarativeAll>): void { builder .fromEvery(_ => _ .set(m => m.lastModified) .toEventContextProperty('occurred') .excludeChildProjections()) .from(OrderCreatedDeclarativeAll, _ => _ .set(m => m.status) .toValue('Placed')) .from(OrderShippedDeclarativeAll, _ => _ .set(m => m.status) .toValue('Shipped')); }}FromAll And FromEvery
Section titled “FromAll And FromEvery”| API | Use it when |
|---|---|
FromAll | You are using the .NET declarative projection API and want to express an all-events mapping. |
FromEvery | You want the portable every-event concept, or you are using a client that exposes the concept under that name. |
Prefer event context sources for audit fields because every event has the same context shape. Use event payload properties only when the event contracts intentionally share the same property.