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.