gpt4 book ai didi

asp.net-mvc - 为什么在 MVC 中将实体作为模型传递不是一个好主意?

转载 作者:行者123 更新时间:2023-12-03 21:18:36 26 4
gpt4 key购买 nike

我们正在使用 MVC 2 RC2 开发一个相当大的应用程序,我们收到了一些关于我们使用 Entity Framework 延迟加载方式的反馈。

我们只是在 Controller 中获取实体并将它们作为模型发送到 View ,这导致 View 代码向数据库询问我们在其中使用的导航属性。我们已经阅读了有关此内容的信息,这似乎不是一个好的设计,但我们想知道为什么?

你能帮助我们理解这个设计问题吗?

谢谢!

最佳答案

这里的主要问题是耦合。模型背后的想法,即“MVC”中的“M”,是它没有外部依赖。它是您应用程序的“核心”。设计良好的应用程序架构的依赖树应该如下所示:

+---------------------------------------> 浏览量
| |
| |
| v
Controller ----+-> 模型转换器-----> View 模型
|\|
|\|
v\v
数据访问<----持久化-------->领域模型
|/
|/
v/
映射器------+

现在我意识到仅仅说“这是一个架构,这是你应该使用的”并不能完全令人信服,所以让我解释一下这里发生的事情:

  • Controller 接收请求。
  • Controller 调用某种持久层(即存储库)。
  • 持久层检索数据,然后使用映射器映射到域模型。
  • Controller 使用转换器将域模型更改为 View 模型。
  • Controller 选择必要的 View 并将 View 模型应用于它。

  • 那么,为什么这很好?
  • 域模型有无依赖 .这是一件非常好的事情,这意味着它很容易执行验证、编写测试等。这意味着您可以更改架构中任何其他地方的任何内容,并且永远不会破坏模型。这意味着您可以跨项目重用模型。
  • 持久层返回域模型的实例。这意味着它可以被建模为一个完全抽象的、与平台无关的接口(interface)。需要使用持久层的组件(如 Controller )不承担任何额外的依赖。这是持久层的依赖注入(inject)和可测试性的理想选择。持久性、数据访问和映射器的组合可以存在于它自己的程序集中。在较大的项目中,您甚至可以进一步解耦映射器并使其在通用记录集上运行。
  • Controller 只有两个下游依赖项——域模型和持久层。模型应该很少更改,因为那是您的业务模型,并且由于持久层是抽象的,因此 Controller 几乎不需要更改(除了添加新操作)。
  • View 依赖于单独的 UI 模型。这将它们与域模型的变化隔离开来。这意味着如果您的业务逻辑发生变化,您无需更改项目中的每个 View 。它允许 View “哑”,因为 View 应该是 - 它们只不过是 View 数据的占位符。这也意味着使用不同类型的 UI(即智能客户端应用程序)重新创建 View 应该很简单,或者切换到不同的 View 引擎(Spark、NHaml 等)


  • 现在,当使用 O/R 映射器(例如 Linq to SQL 或 Entity Framework )时,很容易将它们生成的类视为您的域模型。它当然看起来像一个域模型,但它不是。为什么?
  • 实体类与您的关系模型相关联,随着时间的推移,关系模型可能并且将与您的域模型显着不同;
  • 实体类是愚蠢的。很难支持任何复杂的验证场景或集成任何业务规则。这被称为贫血域模型。
  • 实体类具有隐藏的依赖关系。尽管它们可能看起来是普通的 POCO,但实际上它们可能具有对数据库的隐藏引用(即关联的延迟加载)。这最终可能导致与数据库相关的问题冒泡到 View 逻辑,在那里您最不可能正确分析正在发生的事情并进行调试。
  • 但最重要的是, “领域模型”不再独立。 它不能存在于任何具有数据访问逻辑的程序集之外。嗯,它有点可以,如果你真的努力,有办法解决这个问题,但这不是大多数人做的方式,即使你做到了,你会发现域的实际设计模型受限于您的关系模型,特别是 EF 的行为方式。底线是,如果您决定更改持久性模型,您将破坏域模型,而域模型是应用程序中几乎所有其他内容的基础。

  • Entity Framework 类是 不是 域模型。它们是数据关系模型的一部分,碰巧具有与域模型中的类相同或相似的名称。但它们在依赖管理方面是天壤之别。使用从 ORM 工具生成的类作为域模型只会导致架构/设计极其脆弱;您对应用程序几乎任何部分所做的每一次更改都会产生一系列可预测和不可预测的级联效应。

    有很多人似乎认为您不需要一个有凝聚力的、独立的领域模型。通常的借口是(a)这是一个小项目,和/或(b)他们的领域模型实际上没有任何行为。但是小项目变大了,业务规则变得(远)复杂了,而且一个贫乏或不存在的领域模型不是你可以简单地重构掉的东西。

    这实际上是实体即模型设计中最阴险的特征;它似乎工作正常,有一段时间。直到一两年后,当您淹没在缺陷报告和变更请求中,同时拼命尝试将真正的域模型零碎地组合在一起时,您才会发现这是多么大的错误。

    关于asp.net-mvc - 为什么在 MVC 中将实体作为模型传递不是一个好主意?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2330535/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com