5

我正在和自己争论在使用实体框架的项目中创建 ViewModel 类有什么意义?

我目前有一个使用 EntityFramework 的项目。我的解决方案的结构基本上是这样的:

  • UI 项目(包含控制器和视图)
  • 模型项目(包含 EntityFramework 模型)
  • 服务项目(包含与模型项目对话以将模型项目中的实体提供给 UI 项目的服务类)

我的控制器将 Entity Framework 创建的实体直接传递给视图。

它既好又简单。

在过去,我会创建单独的视图模型类并从 EntityFramework 创建的实体映射到这些视图模型。但现在我很难明白这一点。

我目前正在帮助一个项目,该项目从实体框架生成的实体映射到视图模型。它实际上使用AutoMapper来执行此操作。

现在,这一切似乎都是付出了很多努力和代码,却收获甚微。

我在这里错过了什么吗?

4

3 回答 3

13

我可以想到一些单独的视图模型类层是一种好方法的情况,我将尝试用通用 ORM 工具和通用 MVC 框架来解释它们 - 请注意,这两者都不是案例特定于带有实体框架的 ASP.NET MVC 框架(甚至也不适用于 .NET 中的编程......)。

另外:请注意,在以下几段中,我专门指视图模型。我将在本文末尾解决诸如批量分配漏洞之类的问题。

原因 1:只给 View 层所需的数据,仅此而已

这是一个有点“纯粹”的目标——在真正的 MVC 应用程序中,视图层只能访问它目前需要的数据,而没有其他权限。视图模型对象现在成为从视图层到控制器的规范: “这是我需要显示您请求的视图的数据。” 为了遵守基本的 MVC 原则,您需要确保所有关于显示哪些数据的决定都由控制器做出。

换句话说,如果你想显示一个用户的名字和姓氏、用户名和图片,你不需要(或不想)给视图层一个对象,它也有关于用户密码、角色的信息(或者,取一些可能不那么敏感的属性,高度或中间名)。相反,您给视图一个对象,该对象具有名字、姓氏、用户名和图片的属性,而视图只决定如何呈现数据。这样,您就可以确定呈现什么数据的决定留在控制器层中。

原因 2:避免 ORM 工具的跟踪能力出现问题

一些 ORM 工具 - 甚至一些返回常规对象的工具1 - 使用非常复杂的方法来跟踪您从数据层获得的对象的更改,以便更轻松地更改记录。例如,您可能会从数据存储中获取一个对象,更改该实例的一些属性,然后调用save()方法在其他地方,并且对象在数据库中更新。根据 ORM 工具,将您的 ORM 实体转发到视图层可能会产生任何范围的后果,从性能问题(最坏的情况:数据库连接保持打开)到不必要的影响(例如,视图层中的错误会更改数据存储)。为了避免这些,在将实体发送到应用程序管道太远之前,将您的实体重新映射到与您的 ORM 工具无关的“真正的常规对象”。视图模型是实现这一目标的一种(多种方式)。

请注意,这是否必要完全取决于您的 ORM 工具。我不太了解 Entity Framework 的内部工作原理,无法知道您是否需要关心 - 但在 EF 的(非常)早期版本中,这是一个问题,至少在不使用 Code-First 方法时是这样。

结论:你必须关心吗?

不,不一定。如果没有视图模型,您可能会做得很好,在这种情况下,它们只是另一层抽象,除了复杂性之外并没有真正为您的应用程序增加任何东西。这一切都归结为您的 ORM 工具是否对您的代码提出任何要求,以及您是否是“MVC 纯粹主义者”。

旁注:但是批量分配漏洞呢?

Queti-Mporta已经指出批量分配漏洞可能是一个问题。我同意这是一个严重的问题,但我不同意通过使用视图模型来解决它。

对我来说,视图模型是从控制器到视图的数据传输对象,帮助控制器整理和汇总应该显示的数据。为了避免诸如批量分配漏洞之类的问题,我通常使用编辑模型,它与视图模型非常相似,但方向相反——控制器。不是每个人都做出这种区分——我不太在乎你是否这样做。但是使用这个词汇表,我建议在您让用户更改您的数据时始终使用编辑模型,并且仅在对您有帮助时才使用视图模型。


1在 .NET 中,通常称为“POCO”或普通旧 CLR 对象。Java 在 POJO(Plain Old Java Objects)中有它的等价物,如果你能想到一种可以在面向对象编程中使用的语言,那么该语言也有它的等价物。

于 2013-03-13T17:17:39.407 回答
7

我个人喜欢使用 ViewModel,因为它们可以包含特定于视图的信息。但主要是为了防止将我的实体直接暴露在视图上。

另一个好处是避免批量分配漏洞。这些也存在于 Ruby 中

于 2013-03-13T16:48:29.467 回答
2

我会看一下这个问题 What is ViewModel in MVC,它解释了 ViewModel 的用途。

将模型直接从您的实体传递到视图中没有任何问题,但是当您的模型与您需要的数据不完全匹配时,可以使用 ViewModel。

于 2013-03-13T16:46:27.450 回答