sab*_*ito 14 asp.net-mvc entity-framework lazy-loading asp.net-mvc-2
我们正在使用MVC 2 RC2开发一个相当大的应用程序,我们收到了一些关于我们使用实体框架的延迟加载的方式的反馈.
我们只是将实体放在控制器中并将它们作为模型发送到视图,这导致视图代码向数据库询问我们在其中使用的导航属性.我们已经读过这个并且它似乎不是一个好的设计,但我们想知道为什么?
你能帮我们理解这个设计问题吗?
谢谢!
Aar*_*ght 22
这里的主要问题是耦合.模型背后的想法,即"MVC"中的"M",是它没有外部依赖性.它是您应用程序的"核心".精心设计的应用程序架构的依赖关系树应该如下所示:
+---------------------------------------> Views
| |
| |
| v
Controllers ----+-> Model Transformer -----> View Model
| \ |
| \ |
v \ v
Data Access <---- Persistence --------> Domain Model
| /
| /
v /
Mapper ------+
现在我意识到仅仅说"这是一个架构,这就是你应该使用的"并不完全令人信服,所以让我解释一下这里发生了什么:
那么,为什么这样好呢?
域模型没有依赖关系.这是一件非常好的事情,这意味着它很容易执行验证,编写测试等.这意味着您可以在架构中的任何位置更改任何其他内容,它永远不会破坏模型.这意味着您可以跨项目重用该模型.
持久层返回域模型的实例.这意味着它可以被建模为完全抽象的,与平台无关的界面.需要使用持久层(例如控制器)的组件不会采用任何其他依赖项.这对于持久层的依赖注入以及可测试性来说是理想的.持久性,数据访问和映射器的组合可以存在于它自己的程序集中.在较大的项目中,您甚至可以进一步解耦映射器并使其在通用记录集上运行.
Controller只有两个下游依赖项 - 域模型和持久层.该模型应该很少更改,因为这是您的业务模型,并且由于持久层是抽象的,因此几乎不需要更改控制器(除了添加新操作).
视图取决于单独的UI模型.这使它们与域模型中的更改隔离开来.这意味着,如果业务逻辑发生更改,则无需更改项目中的每个视图.它允许视图"哑",因为视图应该是 - 它们不仅仅是视图数据的占位符.它还意味着使用不同类型的UI(即智能客户端应用程序)重新创建视图应该很简单,或者切换到不同的视图引擎(Spark,NHaml等)
现在,当使用诸如Linq to SQL或Entity Framework 之类的O/R Mapper时,将它们生成的类视为域模型是非常诱人的.它当然看起来像一个领域模型,但事实并非如此.为什么?
实体类与您的关系模型相关联,随着时间的推移,它可以并且将与您的域模型显着不同;
实体类是愚蠢的.很难支持任何复杂的验证方案或集成任何业务规则.这被称为贫血域模型.
实体类具有隐藏的依赖项.尽管它们看似普通的POCO,但它们实际上可能隐藏了对数据库的引用(即关联的延迟加载).这最终可能导致与数据库相关的问题冒泡到视图逻辑,在那里您最不能正确分析正在进行的调试和调试.
但最重要的是,"领域模型"不再是独立的. 它无法生活在具有数据访问逻辑的程序集之外.那么,它有点可以,有办法去了解这一点,如果你真的在它的工作,但它不是像大多数人做到这一点,即使你退出这个功能,你会发现,实际设计领域的模型受限于您的关系模型,特别是EF的行为方式.最重要的是,如果您决定更改持久性模型,则会破坏域模型,并且您的域模型是应用程序中其他所有内容的基础.
实体框架类不是域模型.它们是数据关系模型的一部分,并且碰巧具有与域模型中的类相同或相似的名称.但在依赖管理方面,它们是世界分开的.使用ORM工具生成的类作为域模型只能导致极其脆弱的体系结构/设计; 您对应用程序的几乎任何部分所做的每一项更改都将具有一系列可预测且不可预测的级联效果.
有很多人似乎认为您不需要一个有凝聚力的独立域模型.通常借口是(a)它是一个小项目,和/或(b)他们的域模型实际上没有任何行为.但是小型项目变得越来越大,业务规则变得越来越复杂,并且贫乏或不存在的域模型不是你可以简单地重构的东西.
事实上,这是实体 - 模型设计中最阴险的特征; 它似乎工作正常,暂时.你不会找到多少错误的,这是直到一两年下来,当你淹没在缺陷报告和变更请求,同时拼命地零碎拼凑一个真正的域模型的道路.
| 归档时间: |
|
| 查看次数: |
1876 次 |
| 最近记录: |