我正在尝试实现一个查询,以从域模型管理的数据库中获取一些数据投影到MVC 视图。
我读过返回静态视图的 MVC 控制器应该从查询处理程序或所谓的读取模型存储库请求DTO ,而不是使用返回完整域对象的聚合根存储库。通过这种方式,我们可以最大限度地提高性能(优化对所需数据的查询)并降低域模型滥用的风险(我们不会意外地使用 DTO 更改模型)。
问题是某些DTO 属性不能直接映射到DB Table 字段,并且可能会根据某些业务规则填充,或者是 DB 中未隐式说明的某些条件的结果。这意味着查询作用于从 domain 泄漏的一些逻辑。我听说这是不对的,查询应该直接从数据库表中过滤、排序、投影和聚合数据(在我的例子中使用 linq 查询和 EF)。
到目前为止,我设想了两种解决方案:
1)在内部读取模型存储库,查询完整的域模型对象,使用它们来填充DTO 属性(重要的是那些需要它们的一些业务逻辑才能使用的属性)。在这里,当我们对实例化的域模型进行操作时,我们不会获得性能优势。
2)另一种解决方案是通过可能的域存储库(处理聚合根)将所有需要的数据缓存在数据库中,因此查询对数据字段(具有缓存值)起作用,而不涉及域逻辑。然后,缓存数据的一致性将由域存储库维护,这也会导致一些开销。
例子:
1) 业务规则可以像某些对象或数据(跨系统)的字符串表示一样简单,即格式化;
2)业务规则可以计算字段返回布尔值,如下面的简单领域模型:
// first aggregate root
public class AssignedForm
{
public int Id {get;set}
public string FormName {get;set}
public ICollection<FormRevision> FormRevisions {get;set}
public bool HasTrackingInformation
{
get
{
return FormRevisions.Any(
fr=> fr.RevisionType==ERevisionType.DiffCopy
&& fr.FormRevisionItems.Any)
}
}
public void CreateNextRevision()
{
if(HasTrackingInformation)
{
.......
}
.......
}
}
public enum ERevisionType { FullCopy=0,DiffCopy=1 }
public class FormRevision
{
public int Id {get;set}
public ERevisionType RevisionType {get;set}
public ICollection<FormRevisionItem> FormRevisionItems {get;set}
}
然后我们有一个读取模型存储库,比如IFormTrackingInfoReader返回对象集合
public class FormTrackingInfo
{
public int AssignedFormId {get;set}
public int AssignedFormName {get;set}
public bool HasTrackingInformation {get;set}
}
问题是如何实现IFormTrackingInfoReader并按照 DRY 原则填充HasTrackingInformation属性,并且不会将域泄漏到 query中。我看到人们只是返回域对象并使用映射来填充视图模型。大概这是要走的路。谢谢您的帮助。