6

我正在使用带有实体框架的 asp.net mvc 并开始学习 DDD。我正在从事包含调查的项目。这是我的域模型:

public class Survey
{
    public int? SurveyID { get; set; }
    public string Name { get; set; }
    public decimal MinAcceptanceScore { get; set; }
    public int UserFailsCount { get; set; }

    public IEnumerable<SurveyQuestion> Questions { get; set; }
    public IEnumerable<Prize> Prizes { get; set; }
    public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
}

我需要针对不同视图进行不同部分的调查,因此我创建了不同的 ViewModel:

    public class ShortSurveyViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public int UserFailsCount { get; set; }
        public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
    }

    public class ShortSurveyWithPrizesViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public int UserFailsCount { get; set; }
        public IEnumerable<SurveyAttempt> UserAttempts { get; set; }
        public IEnumerable<Prize> Prizes { get; set; }
    }

    public class SurveyEditViewModel
    {
        public int? SurveyID { get; set; }
        public string Name { get; set; }
        public decimal MinAcceptanceScore { get; set; }
        public int UserFailsCount { get; set; }

        public IEnumerable<SurveyQuestion> Questions { get; set; }
        public IEnumerable<Prize> Prizes { get; set; }
    }

如果我希望我的调查存储库获取适当视图模型所需的信息,那么构建我的架构的最佳方式是什么?

我看到的不同解决方案:

  1. Repository 可以将 IQueryable 返回到 SurveyService 并且 service 可以返回适当的视图模型,但我犹豫这样做是否正确,因为我认为视图模型应该在 UI 中创建,而不是在服务层中创建。

  2. 在我的领域层中创建三个适当的类。但是现在域将依赖于表示,并且每个新视图都应该创建新的域类。

  3. 检索完整的域对象并仅映射特定视图所需的属性。这不好,因为在我的示例中,问题只需要一种表示形式,并且可能是大量收集。

4

2 回答 2

9

领域驱动设计:

  • 您应该有一个返回聚合根的存储库 - 在您的情况下Survey以及所有没有父级就无法存在的关系Survey
  • 该存储库将始终加载整个Survey类,并且根据您的要求仅加载一些关系(真正教条的 DDD 将始终加载整个聚合,但这对于无状态 Web 来说不是一个好方法)。
  • 您的应用程序层(控制器)将向存储库询问Survey和选择关系并填充视图模型。

洋葱架构:

  • 您将创建一些暴露的存储库IQueryable<Survey>- 更糟糕的是,您将使用带有 CRUD 接口的通用存储库
  • 您将创建一些服务调用存储库并将 Linq-to-entities 投影构建到您的 DTO 中并将它们返回到应用程序层(控制器)
  • 怎么办?您可以直接使用这些 DTO,也可以使用另一组对象作为您的视图模型以及一些与 UI 相关的属性等。显然有问题......

简单的架构:

  • 您将直接在控制器中使用注入IDbSet<Survey>作为存储库
  • 您将直接在控制器中进行 Linq 到实体的投影以填充视图模型

没有最好的办法。它始终与您的目标和期望有关。对于小型应用程序,您可以毫无问题地使用简单的架构。

领域驱动设计更复杂。DDD 中的主要概念是领域实体、值对象及其组合。域实体封装了数据和在这些数据上执行的逻辑。DDD 不适用于部分数据或 DTO - 当您的域实体没有任何逻辑时,您做错了(称为贫血模型)。DDD 中的服务不是应用层和存储库之间的中介。它用于处理与单个域实体无关的业务逻辑(因此不能封装在域实体中)。存储库是从存储中实现聚合并将它们持久保存在存储中所需的基础架构代码。应用程序逻辑(控制器)可以与域实体、服务和基础设施代码进行交互。

我不喜欢洋葱架构。

于 2013-03-20T19:16:55.497 回答
0

考虑到您主要关心的是从数据模型中检索到的数据量与视图模型中所需的数据量,我想说对您来说正确的方法是在数据库及其各自的数据模型中构建视图.

这将允许您在任何一次旅行中修剪从数据库中利用的数据量。

尽管数据模型几乎可以模仿视图模型,但这不是问题,它们有两个不同的目的。View Model 是为 View 绑定的——Data Model 知道如何获取和保存数据。构建这些视图将使您能够以最佳方式获取数据 - 同时在这些相同模型中容纳自定义保存逻辑以使它们在必要时可写 - 因此需要数据模型过去将数据从一层移动到下一层。

于 2013-03-20T18:52:18.470 回答