views:

203

answers:

2

Hi all,

I am currently in the process of designing/implementing a repository pattern in a .NET application. After many days of research I feel I am getting close but there really is so many ideas and opinions out there I was hoping to get some peoples thoughts on any design considerations they may have had if you've implemented one yourself already. So...

So the major design issue I'm facing is... Generic Vs Specific Repositories? There's a lot of stuff on this out there and I've done a lot of thinking on this and am still undecided. I will be implementing a IRepository interface and Repository base class. The decision then is whether to leave the repository implementation like this or make the Repository class an abstract class and extend it via specific repositories so either:

public Repository<T> Repository : IRepository<T>
instantiated as: Repository<Customer> CustomerRepository = new Repository<Customer>

or

public CustomerRepository CustomerRepository : Repository<T>, ICustomerRepository
instantiated as: CustomerRepository CustomerRepository = new CustomerRepository()

Initially I was definitely for the specific implementation. The amount of code reuse and reduced number of interfaces and classes with a generic repository is a big plus but I deem the contract it defines to be simply too wide. Allowing the data access layer to be queried in virtually any way by outside objects could lead to all kinds of performance and optimization issues (how could a DBA know which queries where being run on the DB without combing through the entire code... possibly up to the UI layer!!!). This lead me to specific repositories, which can inherit from the abstract BaseRepository to take advantage of code reuse, while still defining a narrow contract such via methods like GetCustomerByName().

A good solution I think but the final design I have come too uses the generic repository pattern along with the the specification pattern. This I really like as it allows the queries on the entities to be encapsulated in classes. Very elegant an ensuring the queries are managed as opposed to a free-for-all sale! A couple of caveats though...

1) Does the use of specifications limit the freedom to move to another data source? Specification pattern seems quite easy to leverage into a repository if the data source supports LINQ. So our repository method would be something like:

IEnumerable<T> Query(ISpecification<T> specification);

But what if we wanted to created a repository using an older ADO.Net 2.0 provider. Wouldn't the queries now have to somehow be converted to an SQL query in the repository??? Or the entire table of Customers would need to be read into memory so each individual customer would need to be checked before the matches could be returned to the aggregate. This will be an issue for us... We have a client running a MySQL database that supports .NET 4.0 but also another client with a dated DB2 database which only has a .NET 2.0 provider.

2) and what about in cases where the CRUD tasks on each entity may not be standard. ie. Maybe a customer can't be deleted... Maybe the creation of some other entity doesn't follow the normal creation pattern of other entities? How would this be handled with a generic repository. I do really like the streamlined design of a generic repository with the specification pattern, but I'll be back to specific repositories if this couldn't be supported. Sorry that was so long winded... but it would be great to hear peoples ideas on this?

I would also like to implement Unit Of Work and DI but I want to finalise my repository design before moving ahead.

+1  A: 

Maybe i'm wrong but when looking at your explanation i don't see anything specific to the repository pattern. Your example is covered by simple DAOs Plus if your only problem is different rdbm for different customers, you should be able to have two different confs for your ORM library (if you use one).

Why don't you go with plain simple DAO ? Look here for example http://www.springframework.net/doc-latest/reference/html/nh-quickstart.html (title 42.3.3)

PS: Don't let Patterns control you, you are the Designer not them :-)

edit Here is a discussion on SO about such a thing http://stackoverflow.com/questions/291344/repository-pattern-vs-dal

redben
A: 

Hi

My understanding is that the repository pattern acts like an in-memory collection of objects that the domain can add and receive from. The repository then hides the actual persistance and data specific code from the domain. The domain can then construct queries to be sent to the repository for action. An interface defines the contract the domain has with the repository, and then different repositories can be implemented to hide the persistance model underneath.

Is this not what is represented by what I have talked about above? Obviously removing the ability to query the repository with Get methods moves away from the repository definition of the client being able to query the repository, but I would have thought the overall concept is still the same. Even the link you sent me calls their DAO a repository...

I'm guessing this follows on from the second link you sent where there seems to be a great deal of overlap (and confusion???) about repositories and DALs and whether they are the same thing and where they diverge.

Regardless of whether my implementation is an actual repository or simply just a DAL, will using specifications limit me to a data persistance technology that supports LINQ? (Further, with LINQ having slightly different abilities depending on whether it is LINQ2SQL or LINQ2Whatever, doesn't this result in data access requirements leaking out of the Repository/DAL? And if a generic DAL/repository is provided, how is it possible to cover specific persistance issues in the repository when relevant to a particular entity?

Steven
Each entity is specific, which implies specification for each entity DAO. Of course you'd have them all extend a common abstract DAO/Repo, for the common behaviors (ex. getById ...etc). But since each entity might have different ways to load for example, they'll have, each, a set of behaviors that are specific to the entity they are handling (specification).So, a generic DAO/Repository as a base class to be extended by entity specific DAOs that'll add entity special behaviours.
redben