asp.net - MVC 3 应用程序中的模型、 View 模型、DTO

标签 asp.net asp.net-mvc asp.net-mvc-3 architecture

我有一个包含两个子项目的 Web 解决方案(在 VS2010 中):

  • Domain其中包含 Model类(通过 Entity Framework 映射到数据库表)和 Services哪个(除了其他东西)负责 CRUD 操作
  • WebUI引用域项目

  • 对于我创建的第一个页面,我直接将域项目中的模型类用作强类型 View 中的模型,因为这些类很小,我想显示和修改所有属性。

    现在我有一个页面,它应该只处理相应域模型的所有属性的一小部分。我通过在我的服务类中使用查询结果的投影来检索这些属性。但我需要项目成类型 - 这里是我关于我能想到的解决方案的问题:
  • 我介绍ViewModels住在WebUI项目和曝光 IQueryablesEF data context从服务到 WebUI 项目。然后我可以直接投影到那些 ViewModel 中。
  • 如果我不想公开 IQueryables 和 EF 数据上下文,我将放置 ViewModel Domain 中的类项目,然后我可以直接返回 ViewModel 作为来自 Service 类的查询和投影的结果。
  • 除了ViewModelsWebUI我介绍的项目Data transfer objects它将数据从服务类中的查询移动到 ViewModels .

  • 解决方案 1 和 2 的工作量相同,我倾向于使用解决方案 2 将所有数据库问题保留在一个单独的项目中。但不知何故,在域项目中使用 View 模型听起来是错误的。

    解决方案 3 听起来需要做更多的工作,因为我有更多的类要创建并关心 Model-DTO-ViewModel 映射。我也不明白 DTO 和 ViewModel 之间有什么区别。 ViewModel 不正是我想要显示的 Model 类的选定属性的集合吗?它们不会包含与 DTO 相同的成员吗?为什么我要区分 ViewModel 和 DTO?

    这三种解决方案中的哪一种更可取,其优点和缺点是什么?还有其他选择吗?

    感谢您提前反馈!

    编辑 (因为我的文字墙可能太长了,有人要求我提供代码)

    示例:我有一个 Customer实体 ...
    public class Customer
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public City { get; set; }
        // ... and many more properties
    }
    

    ...并希望创建一个仅显示(并且可能允许编辑)Name 的 View 列表中的客户。在服务类中,我通过投影提取 View 所需的数据:
    public class CustomerService
    {
        public List<SomeClass1> GetCustomerNameList()
        {
            using (var dbContext = new MyDbContext())
            {
                return dbContext.Customers
                    .Select(c => new SomeClass1
                                 {
                                     ID = c.ID,
                                     Name = c.Name
                                 })
                    .ToList();
            }
        }
    }
    

    然后是一个带有操作方法的 CustomerController。这应该怎么看?

    无论是这种方式 (a) ...
    public ActionResult Index()
    {
        List<SomeClass1> list = _service.GetCustomerNameList();
        return View(list);
    }
    

    ......或者更好的方式(b):
    public ActionResult Index()
    {
        List<SomeClass1> list = _service.GetCustomerNameList();
    
        List<SomeClass2> newList = CreateNewList(list);
    
        return View(newList);
    }
    

    关于上面的选项 3,我想说:SomeClass1 (住在 Domain 项目中)是一个 DTO SomeClass2 (住在 WebUI 项目中)是一个 View 模型 .

    我想知道区分这两个类是否有意义。为什么我不总是为 Controller 操作选择选项 (a)(因为它更容易)?有没有理由介绍 View 模型 ( SomeClass2 ) 除了 DTO ( SomeClass1 )?

    最佳答案

    我将通过使用自动映射工具(如 AutoMapper )为您进行映射来解决您的问题。在映射很容易的情况下(例如,如果一个类的所有属性都应该映射到另一个类上具有相同名称的属性)AutoMapper 将能够为您完成所有连接工作,您必须给几行代码注意,两者之间应该有一个映射。

    这样,您就可以在 Domain 中拥有您的实体。 ,以及 WebUI 中的几个 View 模型类,并在某处(最好在 WebUI 或相同的子命名空间中)定义它们之间的映射。您的 View 模型实际上是 DTO,但您不必担心域和 DTO 类之间的转换过程。

    注意:我会 强烈反对 将您的域实体直接提供给 MVC Web UI 的 View 。您不希望 EF 一直“留在”前端层,以防您以后想使用 EF 以外的其他东西。

    关于asp.net - MVC 3 应用程序中的模型、 View 模型、DTO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5995140/

    相关文章:

    javascript - 在 Firefox 中注销后无法关闭选项卡

    asp.net - ASP 支持的 CSS 文件和捆绑

    javascript - 查看数字助手中的数据注释范围

    asp.net-mvc - 将额外数据传递给 EditorTemplate

    javascript - 需要从子 iframe 中更改父 iframe 的@src

    c# - 如何解析具有不同目录级别的页面的 javascript 路径?

    javascript - 如何从 JQUERY 中的 HTML 文档获取 XML 对象

    asp.net-mvc - ASP.NET MVC 4 Web API & Knockout.js

    c# - 如何在 ASP.net MVC4 的 webgird 中绑定(bind) JSON 返回结果值

    C# MVC3加入SDF数据表