利用通用存储库接口

时间:2017-05-22 20:33:56

标签: design-patterns repository repository-pattern

我已经看到了存储库模式的各种用途。我倾向于一种我不太常见的模式,我想知道是否有充分的理由。

模式1:通过注入构造函数

,通过业务对象访问Repo
        Class Teacher : IPerson
        {
            Private IRepository myRepository;

            Internal Teacher(IRepostory repo){
                This.myRepository = repo;
            }

            Public overrides void Save(){
                Repo.Save(this);
            }
        }

示例:

 IPerson p = DataAccess.GetPersonFromId(id);
 p.Name = "Bill";
 p.Save();

优势

  1. 构造函数将是内部的,只能通过工厂模式访问,所以我不担心这里的复杂性。
  2. IPerson强制执行Save()方法但教师不需要知道它是如何被持久化的
  3. 类似于实体框架代理对象
  4. 我可以在Iperson对象上调用Save(),而无需知道它的教师
  5. 申请 - >业务对象 - >存储库看起来像逻辑依赖结构。
  6. 缺点

    1. 业务对象不再是Plain Old C#对象。

    2. 对实体存储库的任何更改都可能需要更改“人员”界面。

    3. 我是否应该使用相同的模式与IFactory?我们是否继续注射服务?

    4. 模式2:直接访问

              IPerson p = DataAccess.GetPersonFromId(id);
              IRepostory repo = DataAccess.GetRepositority()
              p.Name = "Bill";
              repo.Save(p);
      

      优势

      1. 似乎更简单的做事方式。
      2. 缺点

        1. 我不能很好地利用可用于所有派生类型的通用存储库。我想使用一个Irepository接口,它可以接受Person Type并知道如何持久化它。
        2. 摘要

          我倾向于模式1,但几乎每个我看到的例子都使用了模式2的版本。

          主要目标是我不想在应用层中的任何地方使用TeacherRepository。我想完全依赖IRepository。但是,在模式2中看起来我不能这样做,因为Save()需要知道它与教师的交易才能正确地保存数据。

          是否有任何独特的其他模式可以让我使用通用存储库?

1 个答案:

答案 0 :(得分:0)

关于模式1 :它与保持域对象不仅不知道底层存储类型的原则相矛盾,而且还与它必须存储在某个地方的简单事实相矛盾。更多的是,通过应用模式1,您打破了Single Responsibility Principle:您将有两个原因来更改域对象:业务逻辑和存储。而且,从行为的角度来看,要保存不是Teacher的责任,而是存储库的责任。因此,不再需要讨论利弊。 注意:并非所有框架都遵循良好的OOP设计。想想ORM在大多数情况下使用Active Record。他们正在使用“ class Teacher extends ActiveRecord ”之类的东西。或者施加“每个表一个类”等条件。那么,您怎么看?

关于模式2和你的问题:这里你试图强制执行我上面提到的:以某种方式标准化数据访问工作流,以便能够存储任何类型的域对象属性和结构。对象关系映射......你可以这样做,但你必须处理很多缺点。而且你必须认为你的业务在业务逻辑PLUS存储结构方面很重要。更不用说当你必须处理具有更高等级复杂性的查询时缺乏灵活性。最后 - 我听说 - 你甚至会发现有些任务实际上是不可能解决的。

所以,我的建议是让“普通旧”业务对象完全不知道存储,为它们定义特定的存储库,并从外部“绑定它们”(如通过服务)。

实际上,repository是在所谓的data mapper之上的数据访问抽象层。仅数据映射器 - 与底层数据库通信。在你的问题的背景下,你可以在这里找到一个很好的论证:

以下是其他一些资源:

祝你好运。