1 พฤษภาคม 2555 12:58
Hi all I have been reading a lot about this idea of a Repository pattern and although I have come across a few different implementations of it I was wondering what the core idea of it all is...
1. Simply seperate logic from the class / entity?
2. Place all CRUD and search operations within the Repository?
If thats the case would you have a two classes represent an object? For example, in terms of readability I have done something like:
- Created a class called Person which represents a single entity and is simply ONLY a representation of a Person, i.e. forename, surname, title etc.
- Another class called Persons not the S. This allows me to perform CRUD and search operations. This class also implements IList, IEnumerable.
I guess my question is, is the idea of a repository pattern to simply split the logic of CRUD and search operations to another class OR allow one central place to obtain a list or save an object? For instance, from the above example I wouldn't have a Persons class, instead I would have a Repository class which would accept a type T which would then generically return me a collection of type T?
Is it overkill to have two classes representing a singleton and a collection?
Thanks in advance, Onam.
1 พฤษภาคม 2555 14:00ผู้ดูแล
Before it became popular the repository pattern was used all the time by folks who created -Manager or -s classes that allowed them to get access to some entity. That is all the repository pattern really is. Where the terminology comes from is that you ask the repository (data store) for an object (by id, name, whatever) and it returns back that object. How it found the object, whether it came from ADO.NET, EF, thin air, etc is irrelevant. Repositories were often used as the adapter to the underlying DB so they would provide similar functionality including querying ability.
The purpose of the repository is to allow your entity objects to implement the business rules without regard for how the data is persisted. The repository handles that aspect. It also allows your code to be cleaner because you don't have to worry about creating connections and reading/writing data everywhere (or even in a base class). Only the repository has to deal with that.
For unit testing purposes the repository pattern allows you to create an in-memory, testable store to retrieve objects instead of having to hook into each entity's CRUD logic. This is one of the biggest draws.
There are quite a few folks around that are now against the repository pattern. Like everything else it has some issues. Firstly creating a single repository for every possible query can be complicated and inefficient. Some folks use query objects while others use specification objects. It all amounts to the same thing though. Secondly CRUD operations generally require that you keep a context open (especially for LINQ to SQL and EF) so the code doing the CRUD operations still needs to be store aware even if it is just using a repository. Thirdly L2S and EF already have a repository object (DbContext for EF, for example) so creating a custom one seems redundant. But by using the store-specific repository your business layer is more closely tied to the underlying data layer. Whether this is good or bad is up to you. Finally with LINQ being so prevalent any repository would need to expose a queryable interface that can be easily queried for data. Implementing this can be difficult in a repository but L2S and EF expose this already.
As with most patterns you should evalulate it based upon the needs of your project. There are pros and cons to everything so adding complexity just because a lot of people say it is a good thing isn't necessarily the right answer. I also recommend that you read up on patterns from books like Design Patterns and Clean Code.
Michael Taylor - 5/1/2012
1 พฤษภาคม 2555 17:44
I think that the name of repository pattern was coined by Martin Fowler and is generally used in a Domain Model architecture, the point of the repository is to decouple the domain of the software from the underlying data access and provide a clean way using an object-oriented like approach to access your data.
Thirdly L2S and EF already have a repository object (DbContext for EF, for example) so creating a custom one seems redundant.
I agree with everything you wrote just not that the DbContext is an actual repository object, it's a Unit of Work not a Repository, at least not as Martin Fowler and other architects in the industry defines it.
The Unit of Work responsible to take all the data and commit it to the data source in a single process which is actually the job of the DataContext (L2S), ObjectContext (EF4.0) and DbContext (EF4.1+).
In EF4.1 they added the DbSet that was designed to act as the repository.
Another class called Persons not the S. This allows me to perform CRUD and search operations. This class also implements IList, IEnumerable.
Well, just because you choose to use a different convention doesn't change the soul responsibility of these classes.
Here are few problems that might tackles you.
- When you will actually need a collection of persons you will probably end up with PersonCollection rather than just Persons.
- The name is not crystal clear, it's more obvious that Persons is actually a collection of person rather than a repository.
- You might have classes that contains two or more responsibilities a) collection like methods that acts on data b) repository like methods that executes queries; a class should have only one single responsibility.
One generic repository that does it all is not all that brilliant, for small projects it might work, for medium to enterprise projects it will make everything 100 times harder, you can read more about it here.