我在设计模型时遇到了类似的问题,并提出了这个问题,我认为这可能对您有帮助,特别是关于您的第一点。
DDD - 如何实现高性能的搜索存储库.
在搜索方面,我不使用“模型”,而是有专门的搜索存储库返回“Summary”对象......即“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);
}
}