构建视图模型的最佳方法是什么?

时间:2013-03-20 18:28:46

标签: asp.net-mvc entity-framework domain-driven-design viewmodel repository-pattern

我正在使用带有实体框架的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. 存储库可以将IQueryable返回给SurveyService并且服务可以返回适当的视图模型,但我犹豫这样做是对的,因为我认为应该在UI中创建视图模型,而不是服务层。

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

  3. 检索完整的域对象并仅映射特定视图所需的属性。这样做并不好,因为在我的例子中,只需要一个表示中的问题,而且可能是重要的集合。

2 个答案:

答案 0 :(得分:8)

域驱动设计:

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

洋葱建筑:

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

简单架构:

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

没有最好的办法。它始终与您的目标和您的期望有关。对于小型应用程序,您可以使用简单的架构而不会出现任

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

我不喜欢洋葱建筑。

答案 1 :(得分:0)

考虑到您主要关注的是从数据模型中检索的数据量与视图模型中所需的数据量,我认为正确的方法是在数据库中构建视图及其各自的数据模型。

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

虽然数据模型几乎可以模仿视图模型,但这不是问题,它们有两个不同的用途。视图模型用于绑定视图 - 数据模型知道如何获取和保存数据。构建这些视图将允许您以最佳方式获取数据 - 并且在这些相同模型中容纳自定义保存逻辑以在必要时使它们可写 - 因此需要数据模型将数据从一个层移动到下一个层。 / p>