在设计我的模型时,我遇到了类似的问题,并提出了这个我认为可能对你有帮助的问题,尤其是关于你的第一点。
DDD - 如何实现用于搜索的高性能存储库。
在搜索方面,我不使用“模型”,而是使用专门的搜索存储库返回“摘要”对象......即“PlanSummary”。这些只不过是信息对象(可以被认为更像是报告)并且没有在事务意义上使用——我什至没有在我的模型类库中定义它们。通过创建这些专用存储库和类型,我可以实现高性能搜索查询,这些查询可以包含分组数据(例如 PlannedTraining 计数),而无需将聚合的所有关联加载到内存中。一旦用户在 UI 中选择了这些摘要对象之一,我就可以使用 ID 获取实际的模型对象并执行事务操作并提交更改。
因此,对于您的情况,我将为所有三个实体提供这些专门的搜索存储库,并且当用户希望对一个实体执行和操作时,您始终获取它所属的计划聚合。
通过这种方式,您可以获得高性能搜索,同时仍然使用所需的不变量来维护您的单个聚合。
编辑 - 示例:
好的,所以我想实现是主观的,但这就是我在我的应用程序中处理它的方式,以“TeamMember”聚合为例。用 C# 编写的示例。我有两个类库:
模型库包含聚合类,强制执行所有不变量,报告库包含这个简单的类:
public class TeamMemberSummary
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime DateOfBirth { get; set; }
public bool IsAvailable { get; set; }
public string MainProductExpertise { get; set; }
public int ExperienceRating { get; set; }
}
报告库还包含以下接口:
public interface ITeamMemberSummaryRepository : IReportRepository<TeamMemberSummary>
{
}
这是应用程序层(在我的例子中恰好是 WCF 服务)将使用的接口,并将通过我的 IoC 容器(Unity)解析实现。IReportRepository 与基础 ReportRepositoryBase 一样位于 Infrastructure.Interface 库中。所以我的系统中有两种不同类型的存储库 - 聚合存储库和报告存储库......
然后在另一个库 Repositories.Sql 中,我有实现:
public class TeamMemberSummaryRepository : ITeamMemberSummaryRepository
{
public IList<TeamMemberSummary> FindAll<TCriteria>(TCriteria criteria) where TCriteria : ICriteria
{
//Write SQL code here
return new List<TeamMemberSummary>();
}
public void Initialise()
{
}
}
那么,在我的应用层:
public IList<TeamMemberSummary> FindTeamMembers(TeamMemberCriteria criteria)
{
ITeamMemberSummaryRepository repository
= RepositoryFactory.GetRepository<ITeamMemberSummaryRepository>();
return repository.FindAll(criteria);
}
然后在客户端中,用户可以选择其中一个对象,并在应用层对其中一个对象执行操作,例如:
public void ChangeTeamMembersExperienceRating(Guid teamMemberID, int newExperienceRating)
{
ITeamMemberRepository repository
= RepositoryFactory.GetRepository<ITeamMemberRepository>();
using(IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
{
TeamMember teamMember = repository.GetByID(teamMemberID);
teamMember.ChangeExperienceRating(newExperienceRating);
repository.Save(teamMember);
}
}