如何为IAggregateRoot管理Guard.Against.NotFound及外键存在性校验
校验逻辑最佳实践方案
为什么不能放在AddDistrict实体方法里
领域实体的职责仅处理自身内部的领域规则,不需要依赖外部数据库访问能力,存在性校验属于跨实体的外部校验逻辑,放在实体内会破坏领域层的纯净性,也会提高单元测试的复杂度。
推荐的校验放置位置(按优先级排序)
- 应用服务层(首选)
在调用AddDistrict方法前,先通过仓储查询对应CountryId的实体是否存在,不存在直接抛出异常,存在再执行添加逻辑,示例代码如下:
public async Task AddDistrictAsync(int inputCountryId, District newDistrict) { // 优先校验国家存在性 var existCountry = await _countryRepository.GetByIdAsync(inputCountryId); Guard.Against.NotFound(inputCountryId, existCountry, nameof(existCountry)); existCountry.AddDistrict(newDistrict); await _countryRepository.UpdateAsync(existCountry); }
你的测试用例里直接给District赋值不存在的CountryId=2,只要经过这层校验就会抛出NotFound异常,测试自然会按预期失败。
- 数据库外键约束(兜底方案)
可以在表结构配置时给District表的CountryId字段添加外键关联Country表的主键,一旦插入不存在的CountryId,数据库会直接抛出外键冲突异常,在上层统一捕获处理即可,作为业务校验之外的兜底保障。
额外优化建议
你当前的代码中将District实现了IAggregateRoot是不合理的,从业务关系来看District属于Country聚合下的子实体,不需要作为独立聚合根存在,调整后也能避免跨聚合的校验逻辑混乱。
内容的提问来源于stack exchange,提问作者Danijel Boksan
相关产品推荐
相关产品推荐

