如何在使用仅具有ID引用的聚合时将UI模型设计为另一个聚合

时间:2015-11-16 12:27:04

标签: asp.net-mvc entity-framework entity-framework-6 domain-driven-design cqrs

我读过Vaughn(红皮书的作者)3部分有效聚合设计系列here

鉴于此代码:

public class Transaction
{
            public Guid Id { get; private set; }
            public int Number { get; private set; }
            public DateTime Date { get; private set; }
            public Guid ClientId { get; private set; } // other aggregate reference by ID only
            public Guid BranchId { get; private set; } // other aggregate reference by ID only
            public ICollection<TransactionItem> LineItems { get; private set; }
}

现在在用户界面中,如果我还要显示Branch.NameClient.FullName&amp; Client.Company.Name

我应该创建平面ViewModel吗?

public class ViewModel
{
     // other transaction properties

     public string ClientName {get;set;}
     public string ClientCompanyName {get;set;}
     public string BranchName {get;set;}
}

或具有复杂类型的ViewModel?

public class ViewModel
{
     // other transaction properties

     public ClientDto { get; set; } // companyName and other details inside
     public string BranchName {get;set;}
}

还是有更好的方法吗? 我想尽可能少写代码,但仍保持我的域模型清洁。

现在我正在编写原始sql(数据库视图)并将结果映射到ViewModel,有时我映射到数据库视图并创建映射,以便Entity Framework将结果具体化为viewmodel。

我还需要为我的视图返回的字段添加别名,以避免名称冲突。

但由于代码量不足,感觉不对。

使用数据库/原始sql是否可行?

AutoMapper可以帮我解决这个问题吗?

如果您可以分享您的操作方式,我也有兴趣查看您的代码。

1 个答案:

答案 0 :(得分:2)

  

&#34;使用数据库/原始sql是否可行?&#34;

这将指的是今天许多人采用的称为CQRS的架构,其基于命令和查询是应由不同解决方案解决的不同问题的前提。单个统一模型通常必须双向拉伸,并且最终会比具有两个模型的可维护性,集中性和性能更差。

域模型针对处理命令进行了优化,因此尝试查询它是很痛苦的。您经常最终只需要调用许多存储库来构建一个中等复杂的视图模型。

但是,您经常会读到CQRS绑定到事件源并具有命令总线,通过投影更新的不同读取数据库并且必须异步处理命令。如果您正在构建高度并发的系统,那么您可能会受益于所有这些模式,但大多数系统永远不会需要它,并且使用这些技术会引入意外的复杂性。这是一篇关于CQRS Myths的有趣文章。

如果您使用的是RDBMS,那么我建议您只是绕过查询的域模型,但没有单独的读取数据库。

此外,关于您的平面与非平面视图模型问题,我会选择对消费者最实用的表示。但是,我赞成一个不平整的结构,因为它允许你创建有意义的整体(组高度凝聚力的数据)。通过将它们组合在一起,从现有视图模型构建更复杂的视图模型也可能更容易。