如何在存储库模式中为同一个接口使用两个数据存储?

时间:2014-02-13 18:05:36

标签: repository-pattern data-access-layer business-logic-layer

从TDD的角度来看,我清楚地了解了什么存储库模式及其重要性。我也理解为应用程序切换底层数据存储是多么容易,因为Repository充当数据访问逻辑的窗口。

我没有得到的是如何同时支持多个数据存储。这是一个例子,假设我已经定义了一个存储库IPersonRepository,它有两个实现,并且要求是读取XML文件并存储到SQL数据库中,反之亦然。

DataAccessLayer

public interface IPersonRepository  
{  
    Person GetPersonById(int id);  
}  

public class PersonRepositorySQL : IPersonRepository  
{  
    public Person GetPersonById(int id)  
    {  
        // get person from sql db (using ado.net)  
    }  
}  

public class PersonRepositoryXML : IPersonRepository  
{  
    public Person GetPersonById(int id)  
    {  
        // get person from xml file  
    }  
}  

BusinessLogicLayer

public PersonService   
{  
    private IPersonRepository personRepository;  

    public PersonService(IPersonRepository personRepository)  
    {  
        this.personRepository = personRepository;  
    }  

    public Person GetPersonById(int id)  
    {  
        personRepository.GetPersonById(id);  
    }  
}  

问题(按重要性排序):

  1. 这是否意味着我必须每次实例化两个PersonService对象,分别通过传递PersonRepositorySQL和PersonRepositoryXML来从db和xml读取数据?
  2. 为了做到这一点,我必须在上层添加对存储库的引用(主要是演示文稿)?如何避免这种情况?
  3. DAL是保存存储库的好地方吗?
  4. 将BLL类命名为Service ex:PersonService可以吗?
  5. 我意识到这个帖子已经变得很长但我想把所有引起混淆的事情都记在心里。

    - NV

2 个答案:

答案 0 :(得分:2)

  

这是否意味着我必须每次实例化两个PersonService对象,分别通过传递PersonRepositorySQL和PersonRepositoryXML来从db和xml读取数据?

不,但你正朝着正确的方向前进。我会将两个存储库注入服务(两个构造函数args)并编写两个服务方法,一个以一种方式移动数据,另一种方式移动另一种方式。

连接两个存储库而不是客户端应该是服务的责任。

然后使用IoC容器设置并向客户端提供服务实例,绝对不建议在所有地方使用New Services()。您需要查找最适合您正在使用的演示技术的IoC工具/方法。

  

为了做到这一点,我必须在上层添加对存储库的引用(主要是演示文稿)?如何避免这种情况?

这对于演示是可以的,因为它需要知道要注入到服务实例中的内容,演示文稿是您需要直接引用具体DAL类的唯一地方,并且仅出于这个原因。

我发现Googling for VS分层架构项目结构(或类似的)帮助我在我不太确定的时候回头。

  

DAL是保存存储库的好地方吗?

这就是他们应该去的地方。您的DAL通常用于触及硬件的所有内容,即文件,dbs,webapis。

  

将BLL类命名为Service ex:PersonService?

是否可以

绝对。它简短,甜美,并告诉人们(和其他开发者)它是什么(服务)以及它的责任是什么(人)

答案 1 :(得分:0)

只是为了解决问题#1:您可以实例化一个服务并将Composite传递给它,而不是实例化两个服务。为此,您需要一个可以创建适当Composite的CompositeRepositoryFactory类型。请注意

更多关于Composite和您的具体情况:

  • 它允许您在客户端维护对原始接口的引用时链接多个实现。
  • 允许您链接同一界面的多个实现。这样,实现级联方法调用,允许更丰富的逻辑。另一方面,客户端维护所需的依赖关系:仅在接口本身上。
  • 复合模式有助于SRP原则:如果您的类太广泛并且具有大的接口,您将无法装饰它,因为: 很难精确地实现装饰(因为课程做得太多)。
  • 在下图中:客户端引用CompositeComponent(通过IComponent引用变量)。 CompositeComponent有一个对另一个IComponent实现(例如ConcreteComponent)的引用,它在Something()内有一些逻辑,然后作为该逻辑的一部分 - 它调用ConcreteComponent.Something()。这样,对CompositeComponent.Something()的初始调用级联到ConcreteComponent

Composite Repository diagram

  • 我还创建了一个快速图表,说明上图如何适用于您的案例:您的客户端代码将继续使用PersonService,但不是直接传递某些IPersonRepository实现,你首先去PersonCompositeRepositoryFactory。解决方案根本方面唯一必要的改变是使用PersonCompositeRepositoryFactory

enter image description here