在MVC系统中,数据库持久性代码应该放在哪里?


21

我已经看到了多种用于将信息持久存储到数据库的配置。通常,在我的世界角落,三种类型的设计似乎很常见:

  • 控制器管理持久性
  • 模型管理持久性
  • 第三方库管理持久性,通常需要在模型上进行某种注释。

我想知道从概念上讲哪种配置(如果有的话)最容易使用/与MVC架构最兼容?

(如果不是我列出的人,请给出简短的概述/概述作为答案的一部分)

Answers:


13

您的第二个和第三个选项是相同的。MVC中的M不是数据模型,而是域模型。这包括持久性,无论是直接完成还是通过ORM进行,都完全正确。

控制器应该管理站点的流程,并将内容传递到域(有时通过服务层)进行处理,因此从那里持久存在是错误的-或至少在语义上不舒服。


2
我在一定程度上不同意。持久性的具体利用是应用程序逻辑,因此属于应用程序层而不是域层。域层(包含域模型)应该不考虑临时业务程序的持久性。控制器是协调器。它可以协调(数据)服务,UI和域模型。
猎鹰2012年

1
@Falcon:虽然控制器应该控制何时从数据库中加载数据以及将数据持久存储到数据库中,但是完全可以告诉模型这样做。使用ORM(标准或自用)通常意味着告诉模型加载/保存,然后委派给ORM。另一种方法是让控制器告诉ORM加载/保存某些东西,然后将其传递给模型类以进行加载(使用选择标准)或模型实例进行保存。无论哪种方式,实际的装载/节省都将与模型紧密地联系在一起。
Marjan Venema '02

@Marjan Venema:是的,我同意,但是问题是该代码应该放在哪里。我努力使模型尽可能不了解持久性,并且仅使用其行为和交互来对域实体建模。其他所有内容都将存在于应用程序层中(因为这是我模型的应用程序)。映射信息/数据访问与域模型完全脱钩,并且还可以进行版本控制(升级/降级)。数据访问的应用程序也住在应用层(含服务,仓库等)
猎鹰

@Falcon:是的,这是一种很好的实现方式,也是我过去使用单独的映射类完成此操作的方式。但是,随着扩展的RTTI(Delphi)和反射(.Net等)的出现,我对将它们与Business Object Model属性的注释结合使用以使所有事情顺利进行并没有任何疑虑,而只是使用重载,代码钩子和/或专门编码的初始化类以处理数据库版本控制。
Marjan Venema

5

实际上,MVC主要是一种UI实现模式,因此这个问题有些争议。但是,实际上只有两个大图选项。您的控制器通常使用1)某种服务层或2)Active Record模式调度请求以加载或保存模型中的实体。

服务层可以采用多种形式中的任何一种,尽管我个人偏爱使用聚合根实体的存储库抽象,其具体实现将与某种ORM,轻量级DAO或某些非关系存储的API(如果对应用程序有意义)。

Active Record模式意味着您的模型对持久性负责,尽管它通常意味着某种类型的基类管理到您商店的映射,所以您的模型并没有真正涉及到持久性。

基本上,控制器调度对持久对象的请求,无论这是对存储库,UnitOfWork实现的调用,还是对实体的Save方法的调用。如果使用存储库,则模型对象是持久性忽略的。


3

在MVC(模型视图控制器)系统中,模型包含数据。所以我相信,数据库持久性应该在其中。


2

我见过的大多数高级MVC示例都有一个单独的infrastructure层,其中包含实际的数据库实现代码(即,对NHibernate,EF或Linq或您的数据层的特定调用),而“模型”层(通常也是“域”层)具有定义数据服务的接口


0

MVC中的标准做法是在M(odel)层中包括数据结构和持久性。

模型层不仅包含要在应用程序中使用的类(POCO等)。它们包括这些类的存储库。

一个示例是一个存储库,其中有许多数据类实例,即:

Clients repository

AllClients()
RecentClients()
ClientByID(int id)

您将能够更好地组织模型域,并且可以通过多种方式访问​​数据,但是数据/模型层仍将是紧凑且健壮的

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.