仓储模式 vs ORM

14
使用ORM时,仓储模式有何用处?
例如,假设我有以下(虚构的)数据表: 表:用户
pk_user_id
fk_userrole_id
username

表格:userroles

fk_userrole_id
role

现在使用ORM,我可以将这个放在一个模型文件中:

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

现在$user已经是我的对象了,可以轻松进行延迟加载:

(如果事情能够自动变成单数/复数形式,那就更好了)

foreach ( $user->userroles()->role as $role )
{
    echo $role;
}
现在使用仓储模式需要为用户和角色创建一个仓储。仓储还需要各种函数来检索数据并将其存储。此外,它还需要使用实体模型。所以我不得不创建所有这些。
对我来说,这看起来是很多工作...当我可以像上面描述的那样使用ORM轻松获取数据。而且我也可以轻松地存储数据:
ORM::store($user);
在这种情况下,它不仅会将用户对象存储到数据库中,还会存储我对“Roles”对象所做的任何更改。因此,没有必要进行额外的工作,就像您在仓储模式中需要的那样...
因此,我的问题基本上是,为什么我要在ORM中使用仓储模式?我看过使用该模式的教程(如Doctrine)。但是实际上,它对我来说毫无意义...有人能解释一下它与ORM结合使用的原因吗..??

ORM是一种反模式。http://seldo.com/weblog/2011/06/15/orm_is_an_antipattern - GordonM
我不能说我同意那篇帖子,特别是对于现代ORM。它可以为您懒加载关系,并且您可以轻松指定所需的列(如果需要的话)。 - w00
@w00 你的观点并不孤立... 在这里可以看到一些有关 Repository 作为反模式的讨论: http://ayende.com/blog/3955/repository-is-the-new-singleton - ngm
2个回答

29

ORM是仓储库的一个实现细节。ORM只是使以面向对象的方式轻松访问数据库表格。就是这样。

仓储库用于抽象持久性访问,无论使用什么存储。这是它的目的。使用数据库、XML文件或ORM并不重要。仓储库允许应用程序的其余部分忽略持久性细节。通过模拟或存根轻松测试应用程序,并且可以在需要时更改存储。今天您可能使用MySql,明天您可能想要使用NoSql或云存储。使用 ORM 来解决这个问题!

仓储库处理领域/业务对象(从应用程序角度),ORM处理数据库对象。业务对象不是数据库对象,前者具有行为,后者是一种被吹嘘的数据传输对象,只保存数据。

编辑:你可能会说,仓储库和ORM都抽象了对数据的访问,但魔鬼在细节中。仓储库抽象出所有存储相关的问题,而ORM抽象了对特定关系型数据库管理系统的访问。

简而言之,仓储库和ORM有不同的目的,正如我上面所说,ORM始终是仓储库的实现细节。

您还可以查看有关仓储库模式更多详细信息的此文章


4
ORM和存储库模式...取决于设置。
  1. 如果您将ORM实体用作域层,则请不要使用存储库。
  2. 如果您有单独的域模型,并且需要从该模型映射到ORM实体,因此执行保存操作,则需要使用存储库。

更多详细信息请在此处查看(但必须登录到LinkedIn)。还要了解差异,请查看存储库模式的定义

大多数人使用称为存储库的类,但它们根本不是存储库,只是查询类 - 如果您决定选择#1选项(请参见上面的答案),则应该在这里放置查询。在这种情况下,请确保不要从查询类中公开DbContext或ISession,也不要从那里公开CUD方法 - 记住,查询类!

#2选项很难。如果您真正使用存储库,存储库接口上的所有输入和输出都将包含清晰的域类(而不是数据库相关对象)。禁止从那里公开ORM映射的类或ORM架构相关对象。还将有一个保存方法。这些存储库也可能包含查询,但与查询类不同,这些存储库将执行更多操作 - 它们将获取您的域聚合(实体集合和树),通过将这些类映射到ORM类并在ORM上执行保存来将它们保存到DB。此样式(#2)不需要使用ORM,存储库模式主要用于ADO.NET(任何类型的数据访问)。

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

当有人谈论UnitOfWork时,我也会小心,特别是与ORM一起使用时。互联网上几乎每个示例在架构方面都失败了。如果您需要UoW,为什么不使用TransactionScope(只需确保您有一个默认情况下使用其他Serializable事务的包装器即可)。在99.9%的情况下,您不需要管理两组独立的数据更改(因此需要2组OuW),因此TransactionScope将是.NET的一个不错选择-对于PHP,我会寻找一些开放式会话视图实现...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接