Repository pattern and Dependency Injection without an ORM

I want to implement the repository pattern in an old legacy project.

I already did some research, and found that, without an ORM, it’s completely acceptable to have methods like “GetBySpecialProperty”, and skip the creation of a generic repository.

My current setup is:

public class FooRepository
{
    private IMapper<Foo> _fooMapper;

    public FooRepository (IMapper<Foo> mapper)
    {
        _fooMapper = mapper;
    }

    public List<Foo> GetBySpecialProperty(int specialProperty)
    {
        var result = new List<Foo>();
        //retrieve datareader
        while (reader.Read()) result.Add(_fooMapper.Map(reader));
        return result;
    }
}

My problem now is:
I’d really like to have an interface for this class and be able to inject it into business classes (For testing and to reduce coupling), but it feels wrong to have an IFooRepository interface just for that method.
Plus, I really don’t know how I would make a factory for my repositories, as the caller would have to know the special methods inside the repository he wants.

PS: to access data I’m currently using OleDb, and switching to an ORM is not an option, as the rest of the team doesn’t know how to use them.

Other SE questions I already browsed:
https://stackoverflow.com/questions/5017969/repository-pattern-without-an-orm
https://stackoverflow.com/questions/14293053/data-access-layer-without-orm

2

It seems like you wan to mix two patterns, the ‘generic repository’ and ‘normal repository’

if you have

IRepository
{
    List<Foo> GetFoosByDate(DateTime date);
    List<Foo> GetFoosById(string Id);
}

that is fine and some would say better than

IRepository<T>
{
   List<T> GetThings(IQueryObject query);
}

As the former specifies the allowed queries.

However you could inject the specific repo into a generic wrapper and just throw exceptions when the query didn’t match one of the allowed queries.

3

There is nothing wrong with creating an interface for one method. The important things you accomplish with this are:

  1. Separating concerns. This is data access code and belongs in its own class.

  2. Interface segregation. By using an interface you can expose previously untestable code to unit tests.

These are your big wins that justify an interface with a single method.

I really don’t know how I would make a factory for my repositories, as the caller would have to know the special methods inside the repository he wants.

You should organize your repositories around a single table in the database and any auxiliary information related to that table that is commonly used in conjunction with data from that one table. The factory class just needs to return something that implements the interface. The factory itself should have its own interface so you can inject that into other code.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *