I have repositories (e.g. ContactRepository, UserRepository and so forth) which encapsulate data access to the domain model.
When I was looking at searching for data, e.g.
- finding a contact whose first name
starts with XYZ -
a contact whose birthday is after
1960(etc),
I started implementing repository methods such as FirstNameStartsWith(string prefix) and YoungerThanBirthYear(int year), basically following the many examples out there.
Then I hit a problem – what if I have to combine multiple searches? Each of my repository search methods, such as above, only return a finite set of actual domain objects. In search for a better way, I started writing extension methods on IQueryable<T>, e.g. this:
public static IQueryable<Contact> FirstNameStartsWith(
this IQueryable<Contact> contacts, String prefix)
{
return contacts.Where(
contact => contact.FirstName.StartsWith(prefix));
}
Now I can do things such as
ContactRepository.GetAll().FirstNameStartsWith("tex").YoungerThanBirthYear(1960);
However, I found myself writing extension methods (and inventing crazy classes such as ContactsQueryableExtensions all over, and I lose the “nice grouping” by having everything in the appropriate repository.
Is this really the way to do it, or is there a better way to achieve the same goal?
@Alex – i know this is an old question, but what I would be doing would be letting the Repository do really simple stuff only. This means, get all records for a table or view.
Then, in the SERVICES layer (you are using an n-tiered solution, right? 🙂 ) i would be handling all the ‘special’ query stuff there.
Ok, example time.
Repository Layer
Nice and simple.
SqlContextis the instance of yourEF Context.. which has anEntityon it calledContacts.. which is basically your sql Contacts class.This means, that method basically is doing:
SELECT * FROM CONTACTS… but it’s not hitting the database with that query .. it’s only a query right now.Ok .. next layer.. KICK … up we go (Inception anyone?)
Services Layer
Done.
So lets recap. First, we start our with a simple ‘Get everything from contacts‘ query. Now, if we have a name provided, lets add a filter to filter all contacts by name. Next, if we have a year provided, then we filter the birthday by Year. Etc. Finally, we then hit the DB (with this modified query) and see what results we get back.
NOTES:-
Takeaway points
Good luck 🙂