scaffold-aggregate
Create a new event-sourced aggregate with proper Apply methods, event handling, and Marten configuration. Use this when adding a new domain entity that needs event sourcing.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Follow this guide to create a new event-sourced aggregate in the ApiService following strict Event Sourcing patterns.
-
Define the Initial Event
- Create a
recordinsrc/BookStore.ApiService/Events/ -
Naming: Past tense (e.g.,
AuthorCreated, notCreateAuthor) - Properties: Include all initial state properties
-
IDs: Use
Guidfor aggregate ID -
Timestamp: Use
DateTimeOffset -
Example:
namespace BookStore.ApiService.Events; public record AuthorCreated( Guid Id, string Name, string Biography, DateTimeOffset CreatedAt );
- Create a
-
Create the Aggregate
- Create a
recordinsrc/BookStore.ApiService/Aggregates/ -
Template:
namespace BookStore.ApiService.Aggregates; public record Author { public Guid Id { get; init; } public string Name { get; init; } = string.Empty; public string Biography { get; init; } = string.Empty; public bool Deleted { get; init; } public int Version { get; init; } // Factory method for new aggregates public static Author Create(AuthorCreated @event) { return new Author { Id = @event.Id, Name = @event.Name, Biography = @event.Biography }; } // Apply method for Marten (MUST be void, single parameter) public void Apply(AuthorCreated @event) { // Marten uses this for event replay - do not return anything } // Apply method for subsequent events public void Apply(AuthorUpdated @event) { // Handle state changes } }
- Create a
-
Add Behavior Methods
- Add methods to aggregate that return events
- Pattern: Validate → Return Event
-
Example:
public AuthorUpdated Update(string name, string biography) { if (Deleted) throw new InvalidOperationException("Cannot update deleted author"); if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Name is required", nameof(name)); return new AuthorUpdated(Id, name, biography, DateTimeOffset.UtcNow); }
-
Configure Marten
- Open
src/BookStore.ApiService/Program.cs - Add aggregate to Marten's event store:
builder.Services.AddMarten(options => { // Existing configuration... // Add your aggregate options.Events.StreamIdentity = StreamIdentity.AsGuid; });
- Open
-
Create Unit Tests
- Create test file in
tests/BookStore.ApiService.UnitTests/Aggregates/ -
Test Pattern:
using TUnit.Core; using TUnit.Assertions.Extensions; public class AuthorTests { [Test] public async Task Create_ReturnsValidAggregate() { // Arrange var created = new AuthorCreated( Guid.CreateVersion7(), "Martin Fowler", "Author and speaker", DateTimeOffset.UtcNow ); // Act var author = Author.Create(created); // Assert await Assert.That(author.Id).IsEqualTo(created.Id); await Assert.That(author.Name).IsEqualTo("Martin Fowler"); } [Test] public async Task Update_DeletedAuthor_ThrowsException() { // Arrange var author = new Author { Deleted = true }; // Act & Assert await Assert.That(() => author.Update("New Name", "Bio")) .Throws<InvalidOperationException>(); } }
- Create test file in
-
Verify Analyzer Compliance
- Run
dotnet buildto check for BS1xxx-BS4xxx warnings - Ensure:
- ✅ Events are
recordtypes (BS1001) - ✅ Apply methods are
voidwith single parameter (BS1002) - ✅ Aggregates use proper patterns (BS2xxx)
- ✅ Events are
- Run
-
Next Steps
- Use
/scaffold-projectionto create read models from your aggregate's events - Use
/scaffold-writeto create complete command/handler/endpoint flow - Use
/scaffold-testto create integration tests - Use
/verify-featureto ensure everything works
- Use
Related Skills
Prerequisites:
- None - this is a foundational skill for event sourcing
Next Steps:
-
/scaffold-projection- Create read models from aggregate events -
/scaffold-write- Add commands, handlers, and endpoints for this aggregate -
/scaffold-test- Create integration tests -
/verify-feature- Run all verification checks
See Also:
- scaffold-write - Complete write operation workflow
- event-sourcing-guide - Event Sourcing patterns
- marten-guide - Marten event store integration
- analyzer-rules - Code analyzer rules (BS1xxx-BS4xxx)
- ApiService AGENTS.md - Backend patterns and conventions
Key Rules to Remember
-
Apply Methods: MUST be
voidwith single event parameter (Marten convention) - Behavior Methods: Return events, don't mutate state directly
-
IDs: Use
Guid.CreateVersion7()for new aggregates -
Immutability: Use
recordtypes withinitproperties - Validation: Validate in behavior methods, throw exceptions for invalid operations
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-01-20
- 索引更新时间
- 2026-01-26
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!