Skip to content

Commit 6677d5e

Browse files
authored
Merge pull request #1091 from alexeyfv/docs/read-aggregate-events
Documentation improvements: Reading Aggregate Events
2 parents a446cd4 + 9ee4c5d commit 6677d5e

File tree

1 file changed

+74
-5
lines changed

1 file changed

+74
-5
lines changed

Documentation/basics/aggregates.md

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ The `IAggregateStore.UpdateAsync` method allows to load, modify and save the agg
110110
```csharp
111111
public class TestController(IAggregateStore aggregateStore) : ControllerBase
112112
{
113-
public async Task Ping(Guid id)
113+
public async Task Ping(
114+
Guid id,
115+
CancellationToken cancellationToken)
114116
{
115117
var testId = TestId.With(id);
116118
var sourceId = TestId.New;
@@ -123,7 +125,7 @@ public class TestController(IAggregateStore aggregateStore) : ControllerBase
123125
aggregate.Ping("ping");
124126
return Task.CompletedTask;
125127
},
126-
CancellationToken.None);
128+
cancellationToken);
127129
}
128130
}
129131
```
@@ -157,14 +159,16 @@ await aggregateStore.StoreAsync<TestAggregate, TestId>(
157159
CancellationToken.None);
158160
```
159161

160-
### Using the CQRS approach.
162+
### Using the CQRS approach
161163

162164
Another way to change the aggregate is by following the CQRS (Command Query Responsibility Segregation) pattern.
163165

164166
```csharp
165167
public class TestController(ICommandBus commandBus) : ControllerBase
166168
{
167-
public async Task Ping(Guid id)
169+
public async Task Ping(
170+
Guid id,
171+
CancellationToken cancellationToken)
168172
{
169173
var testId = TestId.With(id);
170174

@@ -175,10 +179,75 @@ public class TestController(ICommandBus commandBus) : ControllerBase
175179
};
176180

177181
// Publish the command using the command bus
178-
await commandBus.PublishAsync(command, CancellationToken.None);
182+
await commandBus.PublishAsync(command, cancellationToken);
179183
}
180184
}
181185
```
182186

183187
For more details on commands and command handlers, check the [documentation](../basics/commands.md).
184188

189+
## Reading aggregate events
190+
191+
To read events for a specific aggregate, you can use the `IEventStore` interface. This allows you to load events for an aggregate by its identity.
192+
193+
### Load all events
194+
195+
In the example below, the `GetAuditLog` method loads **all events** for the specified aggregate and maps them to a DTO.
196+
197+
```csharp
198+
public class TestController(IEventStore eventStore) : ControllerBase
199+
{
200+
public async Task<IEnumerable<EventDto>> GetAuditLog(
201+
Guid id,
202+
CancellationToken cancellationToken)
203+
{
204+
var testId = TestId.With(id);
205+
206+
var events = await eventStore.LoadEventsAsync<TestAggregate, TestId>(
207+
testId,
208+
cancellationToken);
209+
210+
return events.Select(e => new EventDto
211+
{
212+
EventType = e.EventType.Name,
213+
Timestamp = e.Timestamp
214+
});
215+
}
216+
}
217+
218+
public class EventDto
219+
{
220+
public required string EventType { get; init; }
221+
public required DateTimeOffset Timestamp { get; init; }
222+
}
223+
```
224+
225+
### Load events for a specific range
226+
227+
You can also load events for a specific range. In the example below, `from` and `to` represent the range of sequence numbers for the events you want to load. This can be useful for pagination or retrieving a specific subset of events for an aggregate.
228+
229+
```csharp
230+
public class TestController(IEventStore eventStore) : ControllerBase
231+
{
232+
public async Task<IEnumerable<EventDto>> GetEventsInRange(
233+
Guid id,
234+
int from,
235+
int to,
236+
CancellationToken cancellationToken)
237+
{
238+
var testId = TestId.With(id);
239+
240+
var events = await eventStore.LoadEventsAsync<TestAggregate, TestId>(
241+
testId,
242+
from,
243+
to,
244+
cancellationToken);
245+
246+
return events.Select(e => new EventDto
247+
{
248+
EventType = e.EventType.Name,
249+
Timestamp = e.Timestamp
250+
});
251+
}
252+
}
253+
```

0 commit comments

Comments
 (0)