Domain-Driven Design with .NET
Apply Domain-Driven Design tactical and strategic patterns in .NET — aggregates, value objects, domain events, bounded contexts, and ubiquitous language.
55 min•By Priygop Team•Last updated: Feb 2026
DDD Building Blocks
- Entities: Objects with identity that persists over time — Order, Customer, Product. Identity (Id) defines equality, not attributes
- Value Objects: Immutable objects without identity — defined by their attributes. Money(100, 'USD'), Address(street, city, state). Use C# records
- Aggregates: Cluster of entities treated as a unit — Order aggregate contains OrderLines. External objects reference aggregates only by their root Id
- Domain Events: Record that something meaningful happened — OrderPlaced, PaymentReceived. Published in-process or via message broker for cross-boundary communication
- Domain Services: Operations that don't naturally belong to an entity — PricingService.CalculateDiscount() involves multiple aggregates
- Repositories: Abstract persistence — IOrderRepository.GetByIdAsync(). Implementation in Infrastructure layer uses EF Core or Dapper
- Specifications: Encapsulate query logic in domain layer — ActiveOrdersSpec, HighValueCustomersSpec. Reusable, testable, and composable
Strategic DDD Patterns
- Bounded Contexts: Clear boundaries where a domain model applies — 'Customer' in Sales vs 'Customer' in Support are different models with different attributes
- Ubiquitous Language: Team and code use the same terms — if business says 'Order', code uses Order not PurchaseRequest. Language mismatches cause bugs
- Context Mapping: Define relationships between bounded contexts — Customer/Supplier, Shared Kernel, Anti-Corruption Layer, Conformist, Open/Host Service
- Anti-Corruption Layer: Translate between your domain model and external systems — prevents external models from polluting your domain
- Event Storming: Workshop technique for discovering domain events, commands, and aggregates — uses sticky notes and collaborative discussion