12

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

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

表:用户

pk_user_id
fk_userrole_id
username

表:用户角色

fk_userrole_id
role

现在有了一个 orm 我可以简单地把它放在一个模型文件中:

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

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

(如果事物自动单数/复数会更好)

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

现在使用存储库模式,我必须为用户和角色创建一个存储库。存储库还需要各种功能来为我检索数据并存储它。此外,它需要与实体模型一起使用。所以我也必须创建所有这些。

对我来说,这看起来像很多东西......当我可以像上面描述的那样使用 ORM 简单地获取数据时。我可以很容易地存储它:

ORM::store($user);

在这种情况下,它不仅会将用户对象存储到数据库中,还会存储我对“角色”对象所做的任何更改。所以不需要像存储库模式那样做任何额外的工作......


所以我的问题基本上是,我为什么要使用带有 ORM 的存储库模式?我已经看过使用该模式的教程(例如 Doctrine)。但这对我来说真的没有任何意义......任何人对它与ORM结合使用的任何解释......?

4

2 回答 2

21

ORM 是存储库的实现细节。ORM 只是使以 OOP 友好的方式访问数据库表变得容易。而已。

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

存储库处理域/业务对象(从应用程序的角度来看),ORM 处理数据库对象。业务对象不是数据库对象,首先具有行为,其次是美化的 DTO,它只保存数据。

编辑 您可能会说存储库和 ORM 都抽象了对数据的访问,但魔鬼在细节中。存储库抽象了对所有存储问题的访问,而 ORM 抽象了对特定 RDBMS的访问。

简而言之,Repository 和 ORM 有不同的用途,正如我上面所说,ORM 始终是 repo 的实现细节。

您还可以查看这篇文章,了解有关存储库模式的更多详细信息。

于 2012-04-15T08:48:34.863 回答
4

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

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

您可以在此处找到更多详细信息(但必须登录到已链接)。另外要了解差异,请查看存储库模式的定义

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

#2选项是一个艰难的选项。如果你做一个真正的存储库,存储库界面上的所有输入和输出都将包含明确的域类(并且没有与数据库相关的对象)。禁止从那里公开 ORM 映射类或 ORM 架构相关对象。还会有一个 Save 方法。这些存储库也可能包含查询,但与查询类不同,这些存储库将做更多事情 - 它们将获取您的域聚合(实体集合和树)并通过将这些类映射到 ORM 类并将它们保存到数据库并在 ORM 上执行保存。这种风格(#2)不需要使用 ORM,存储库模式主要是为 ADO.NET(任何类型的数据访问)制作的。

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

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

于 2017-02-26T15:24:03.103 回答