【问题标题】:Where to place calculated property of HasChildren for Domain Model?在哪里放置域模型的 HasChildren 计算属性?
【发布时间】:2019-08-24 06:06:23
【问题描述】:

我们有一个Department 模型(领域驱动设计)。每个部门都有自己的子部门,所以领域模型看起来像

public class Department
{
  int Id { get; set; }
  ...
  ICollection<Department> Children { get; set; }
}

在同一层次路径的API域模型,来自repository,会通过AutoMapper转换为DTO槽,默认不包含children。

public class DepartmentDto
{
  int Id { get; set; }
  ...
  ICollection<DepartmentDto> Children { get; set; } // Empty set.
}

[NotMapped] bool HasChildren 属性添加到Department 域模型以在客户端显示或隐藏展开箭头是否是一种好方法?用于延迟加载。

这个字段闻起来很奇怪:可以填写或不填写(取决于查询)。

Repository 返回一个部门的集合,属于parent Id(对于根节点可能变成Null):

ICollection<Department> GetDepartments(int? parentId = null);

【问题讨论】:

  • 您可以从 DepartmentDto 中删除 Children 并添加 HasChildren。
  • 属性Children 正在被其他一些逻辑使用(API 即将推出)。
  • 然后在 dto 中,public bool HasChildren =&gt; Children.Count &gt; 0;
  • 如果您有时不需要孩子,但您需要知道是否有孩子,那么您可以在 AM 配置中计算 HasChildren。例如 ChidrenCount 将自动从源映射,但一定要检查生成的 SQL。检查the docs
  • 也许最好为每种情况使用单独的 dto-s。

标签: domain-driven-design automapper dto


【解决方案1】:

所以,基于Lucian Bargaoanu cmets,我找到了解决方案:

IDepartmentRepository.cs

IQueryable<Department> GetDepartmentsQuery(int? parentId = null);

DepartmentsController.cs (API):

[HttpGet]
public async Task<ActionResult<ICollection<DepartmentDto>>> GetRootDepartments()
{
    var dtoItems = await _repository.GetDepartmentsQuery()
        .ProjectTo<DepartmentDto>(_mapper.ConfigurationProvider)
        .ToListAsync();

    return Ok(dtoItems);
}

AutoMapper 配置:

CreateMap<Department, DepartmentDto>()
  .ForMember(x => x.HasChildren,
      opts => opts.MapFrom(x => x.Children.Any()))
  .ForMember(x => x.Children,
      opts => opts.Ignore());

【讨论】: