repository-patterndata-access-layerbusiness-logic-layer

How to use two data stores for same interface in repository pattern?


I have clear understanding of what repository pattern is and its importance from TDD's standpoint. I also understand that how easy it can be to switch underlying data store for the application because Repository acts as a window to data access logic.

What I am NOT getting is how to support multiple data stores at a same time. Here's an example, assume that I have defined a repository IPersonRepository which has two implementations and the requirement is to read XML file and store into SQL database or vice-versa.

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);  
    }  
}  

Questions (ordered by importance):

  1. Does this mean I have to instantiate two PersonService objects everytime for reading data from db and xml by passing PersonRepositorySQL and PersonRepositoryXML respectively?
  2. For doing above, I have to add reference to repositories in upper level (mostly presentation)? How can this be avoided?
  3. Is DAL good place to keep repositories?
  4. Is it OK to name a BLL class as Service ex: PersonService?

I realize that post has become very long but I wanted to put everything that's causing confusions in mind.

-- NV


Solution

  • Does this mean I have to instantiate two PersonService objects everytime for reading data from db and xml by passing PersonRepositorySQL and PersonRepositoryXML respectively?

    No, but you're heading in the right direction. I would inject both repositories into the service (two constructor args) and write two service methods, one that moves data one way and another the other way.

    It should be the responsibility of the service to connect the two repositories, rather than the client.

    Then use an IoC container to setup and provide the service instance to clients, having New Services() all over the place is definitely not recommended. You'll need to look up the IoC tools/approach that works best for whatever presentation technology you're using.

    For doing above, I have to add reference to repositories in upper level (mostly presentation)? How can this be avoided?

    That's okay for presentation as it needs to know what to inject into the service instance, presentation is the only place you need to reference concrete DAL classes directly and for only that reason.

    I found Googling for VS layered architecture project structure (or similar) helped me heaps back when I wasn't too sure.

    Is DAL good place to keep repositories?

    That's where they should be. Your DAL is generally for everything that touches hardware i.e. files, dbs, webapis.

    Is it OK to name a BLL class as Service ex: PersonService?

    Absolutely. It's short, sweet, and tells people (and other devs) what it is (a service) and what it's responsibilities are (people)