Projection functions
Projections support several built-in functions for mathematical operations and counting. These functions allow you to perform calculations directly within projections without needing custom logic.
Counting events
Section titled “Counting events”Use Count() to increment a counter each time an event is processed:
public class UserActivityProjection : IProjectionFor<UserActivity>{ public void Define(IProjectionBuilderFor<UserActivity> builder) => builder .AutoMap() .From<UserLoggedIn>(_ => _ .Count(m => m.LoginCount)) .From<UserPerformedAction>(_ => _ .Count(m => m.ActionCount));}Read model
Section titled “Read model”The read model contains numeric properties for the counters:
public record UserActivity( string Username, int LoginCount, int ActionCount);Increment and decrement
Section titled “Increment and decrement”Use Increment() and Decrement() to add or subtract 1 from a property:
public class InventoryProjection : IProjectionFor<Inventory>{ public void Define(IProjectionBuilderFor<Inventory> builder) => builder .AutoMap() .From<ItemAdded>(_ => _ .Increment(m => m.Quantity)) .From<ItemRemoved>(_ => _ .Decrement(m => m.Quantity));}These functions always change the value by exactly 1.
Add and subtract with values
Section titled “Add and subtract with values”Use Add() and Subtract() to add or subtract specific values from event properties:
public class AccountProjection : IProjectionFor<Account>{ public void Define(IProjectionBuilderFor<Account> builder) => builder .AutoMap() .From<AccountOpened>(_ => _ .Set(m => m.Balance).ToValue(0m)) .From<MoneyDeposited>(_ => _ .Add(m => m.Balance).With(e => e.Amount)) .From<MoneyWithdrawn>(_ => _ .Subtract(m => m.Balance).With(e => e.Amount));}Supported types
Section titled “Supported types”All projection functions work with these numeric types:
intlongfloatdoubledecimal
The functions automatically handle type conversion and maintain the target property’s type.
Event definitions
Section titled “Event definitions”[EventType]public record UserLoggedIn(string Username);
[EventType]public record UserPerformedAction(string Username, string ActionType);
[EventType]public record ItemAdded(string Name);
[EventType]public record ItemRemoved(string Name);
[EventType]public record AccountOpened(string Number);
[EventType]public record MoneyDeposited(decimal Amount);
[EventType]public record MoneyWithdrawn(decimal Amount);How functions work
Section titled “How functions work”- Initialization: Properties start at 0 (or their default value) when first accessed
- Accumulation: Functions apply their operations incrementally as events are processed
- Type safety: Values are converted to match the target property type
- State preservation: Current values are maintained between events
Combining functions
Section titled “Combining functions”You can use multiple functions in a single projection:
.From<Transaction>(_ => _ .Count(m => m.TransactionCount) .Add(m => m.TotalAmount).With(e => e.Amount) .Increment(m => m.ProcessedEvents))These functions provide powerful aggregation capabilities while keeping projection logic simple and declarative.