2012-04-14 182 views
1

当您拥有ORM时,存储库模式有什么好处?存储库模式与ORM

例子。假设我有以下的(虚构的)表:

表:用户

pk_user_id 
fk_userrole_id 
username 

表:的UserRole

fk_userrole_id 
role 

现在用的ORM我可以简单地把这个模型中文件:

$user = ORM::load('users', $id); 

现在$ USER已经是我的对象,它可以很容易地延迟加载:

(如果事情是自动单/多元状态会更好)

foreach ($user->userroles()->role as $role) 
{ 
    echo $role; 
} 

现在用Repository模式我” d必须为用户创建一个存储库,为角色创建一个存储库。存储库还需要各种函数来为我检索数据并存储它。另外它需要与实体模型一起工作。所以我也必须创造所有这些。

对我来说,看起来像很多东西做...当我可以简单地得到像我上面描述的数据与ORM。我可以像存储它一样简单:

ORM :: store($ user);

在这种情况下,它不仅会将用户对象存储到数据库,而且还会对“角色”对象进行任何更改。因此,没有必要像你需要使用存储库模式的任何额外的工作...


所以我的问题主要是,为什么我会想使用一个存储库模式与ORM?我已经看过教程在哪里使用该模式(比如Doctrine)。但它对我来说真的没有任何意义......任何与ORM结合使用的任何解释.. ??

+0

ORM是一个反模式。 http://seldo.com/weblog/2011/06/15/orm_is_an_antipattern – GordonM 2012-04-14 17:24:17

+0

我真的不能说我同意这个帖子。特别是与现代的手镯。它为你延迟关系,你可以很容易地指定你想要的列(如果你需要)。 – w00 2012-04-14 18:45:42

+0

@ w00在你看来,你并不孤单......在这里可以看到Repository作为反模式的一些讨论:http://ayende.com/blog/3955/repository-is-the-new-singleton – ngm 2012-04-14 19:20:50

回答

3

该ORM是存储库的实现细节。 ORM只是简单地以OOP友好的方式访问数据库表。而已。

存储库抽象持久性访问,无论它是什么存储。这是它的目的。事实证明,你使用的是db或xml文件或ORM并不重要。存储库允许应用程序的其余部分忽略持久性细节。这样,您就可以通过模拟或存根来轻松测试应用程序,并且如果需要,您可以更改存储。你可能会使用MySql,明天你会想使用NoSql或云存储。用ORM来做!

存储库处理域/业务对象(从应用程序的角度来看),ORM处理数据库对象。业务对象不是数据库对象,首先是行为,第二个是荣耀的DTO,它只保存数据。

编辑 您可能会说,存储库和ORM都抽象访问数据,但恶魔是在细节中。存储库抽象的接入所有存储涉及,而ORM抽象访问特定的RDBMS

简而言之,存储库和ORM的有不同的目的,正如我上面所说的,ORM始终是一个回购的实施细节。

您还可以检查this post了解有关存储库模式的更多详细信息。

0

ORM和存储库模式... 取决于设置。

  1. 如果您使用ORM实体作为域图层,那么请不要使用存储库。
  2. 如果您有单独的域模型,并且需要将该模型映射到ORM实体并执行保存操作,那么存储库就是您所需要的。

更多细节,你会发现here(但必须记录到链接)。还要了解差异,请查看存储库模式的definition

大多数人使用他们称之为库,而不是在所有的仓库,只是查询类类 - 这是怎么了/你应该把你的查询,如果你决定去与#1选项(见上面的答案)。在这种情况下,请确保不要从该查询类中公开DbContext或ISession,也不要从那里公开CUD方法 - 请记住,Query类!

#2选项是一个艰难的选择。如果您创建了一个真实的存储库,那么存储库接口上的所有输入和输出将包含清除的域类(并且不包含与数据库相关的对象)。禁止从那里暴露ORM映射类或ORM体系结构相关对象。还会有一个Save方法。这些存储库也可能包含查询,但与查询类不同,这些回购将会做更多的事情 - 它们将采取您的域聚合(实体的集合和树)并将它们保存到数据库,方法是将这些类映射到ORM类并在ORM上执行保存。这种风格(#2)不需要使用ORM,存储库模式主要用于ADO.NET(任何类型的数据访问)。

无论如何,这2个选项是我们可以做的两个极端。 很多人使用ORM的存储库,但他们只是增加了一层额外的代码,没有真正的功能,唯一真正的功能就是查询类的行为。

另外,当有人谈论UnitOfWork时,尤其是使用ORM,我会小心的。几乎互联网上的每一个样本在架构方面都是失败的。如果你需要UoW,为什么不使用TransactionScope(只要确保你有一个默认使用不同于Serializable事务的包装器)。在99,9%的情况下,你不需要管理2组独立的数据更改(因此2组OuW),所以TransactionScope在.NET中将是一个很好的选择 - 对于PHP,我会寻找一些开放会话 - 查看实现...