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; } }
如果我希望我的调查存储库获取适当的视图模型所需的信息,那么构建我的架构的最佳方法是什么?
我看到不同的解决方案:
>存储库可以将IQueryable返回给SurveyService并且服务可以返回适当的视图模型,但我犹豫这样做是对的,因为我认为应该在UI中创建视图模型,而不是服务层.
>在我的域图层中创建三个适当的类.但是现在域将依赖于表示,并且每个新视图都应该创建新的域类.
>检索完整的域对象并仅映射特定视图所需的属性.这并不好,因为在我的例子中,只需要一个表示中的问题而且它可能是大量收集.
解决方法
>您应该有一个存储库返回聚合根 – 在您的情况下调查和所有没有父调查不可能存在的关系
>这个存储库将加载整个Survey类,并根据您的要求只是一些关系(真正教条DDD总是会加载整个聚合,但这对于无状态Web来说不是一个好方法).
>您的应用程序层(控制器)将询问存储库以查看调查和选定的关系并填充视图模型.
洋葱建筑:
>您将创建一些暴露IQueryable< Survey>的存储库. – 更糟糕的是,您将使用具有CRUD接口的通用存储库
>您将创建一些服务调用存储库并将Linq到实体投影构建到您的DTO中并将它们返回到应用程序层(控制器)
>现在怎样?您可以直接使用这些DTO,也可以使用另一组用作视图模型的对象以及一些与UI相关的属性等.显然有些问题……
简单的架构:
>您将使用注入的IDbSet< Survey>直接在您的控制器中作为存储库
>您将直接在控制器中进行Linq到实体投影以填充视图模型
没有最好的办法.它始终与您的目标和您的期望有关.对于小型应用程序,您可以使用简单的架构而不会出现任
域驱动设计更复杂. DDD的主要概念是域实体,值对象及其组成.域实体封装在这些数据上执行的数据和逻辑. DDD不适用于部分数据或DTO – 当您的域实体没有任何逻辑时,您做错了(它被称为贫血模型). DDD中的服务不是应用程序层和存储库之间的中介.它用于处理与单域实体无关的业务逻辑(因此不能封装在域实体中).存储库是从存储中实现聚合并将其存储在存储中所需的基础结构代码.应用程序逻辑(控制器)可以与域实体,服务和基础结构代码交互.
我不喜欢洋葱建筑.