Domain driven design 从积垢到DDD
我有一个管理门票和客户的应用程序。一位顾客拥有许多票。如果客户被删除,其票据也会被删除。这是查看对象是否应为聚合的测试之一。我选择它们都应该是不在聚合根下的实体。我通常会加载并显示跨越许多客户的门票列表。我正在使用SQL Server以关系格式保存数据 我的架构如下所示:Domain driven design 从积垢到DDD,domain-driven-design,Domain Driven Design,我有一个管理门票和客户的应用程序。一位顾客拥有许多票。如果客户被删除,其票据也会被删除。这是查看对象是否应为聚合的测试之一。我选择它们都应该是不在聚合根下的实体。我通常会加载并显示跨越许多客户的门票列表。我正在使用SQL Server以关系格式保存数据 我的架构如下所示: ASP.NETMVC应用程序 WCF服务(门面)。此服务具有公共方法,例如GetTicket、GetTickets、GetCustomer和GetCustomers。为此,它直接使用存储库。它还有一个名为Run的公共方法。Ru
要清楚的是,域模型(其中实体和值对象被组装成聚合体)和数据模型(它实际上只是所选OOP语言中数据库的代码表示)之间有区别。您的数据模型就是您的表,可能与您的域模型完全不同。数据模型可以在不存在实际引用的表之间建立关系。换句话说,可以跨聚合边界使用外键引用。这只是为了在数据库中强制执行引用完整性。如果要使用ORM将这些表映射到类,则不会有“导航属性”,只有ID值 似乎DDD业务逻辑和UI需要显示的内容之间存在着断开连接 现在我们开始讨论CQR。DDD是关于在您的问题域中建模行为的。一个域模型应该有很多行为(并且可能没有公共状态,我将继续介绍)。在调用域逻辑时,您应该在一个事务中加载聚合,调用所需的行为并保存结果。因此,您的存储库应该如下所示:
public interface IRepository<TEntity>
{
TEntity Get(Guid id);
void Save(TEntity item);
}
公共接口IRepository
{
TEntity-Get(Guid-id);
无效保存(紧急项);
}
实现总是急切地加载所有内容,因为在ORM映射中,您不会在聚合之外包含对实体的引用。事实上,您现在可能已经认为文档数据库更适合存储聚合,我想您是对的
但是你怎么去质疑呢?容易的。写一个查询。如果您正在实现CQR,那么您有一个薄的读取层,不使用存储库,不使用精心编制的实体及其ORM映射。只需编写一个查询。如果使用SQLServer,请考虑使用超快速LINQ到SQL数据上下文,或者使用Doper或Simul.DATA。甚至只是ADO.NET。关键是,您的查询是关于从数据库中获取一些数据,而不需要行为
如果您使用文档数据库进行聚合持久化,那么CQRS模式的合理实现可能会看到您可能使用从域行为生成的事件构建一个完全独立的数据库。“读取存储”的选项是无穷无尽的。以下是一些想法:
- 相同或其他文档数据库实例,但具有预构建的viewmodels
- SQL数据库(您可以放弃第三种标准形式并使用复制,因为您希望优化读取性能而不是OLTP性能)
- 磁盘上预写的HTML文件