I\'ve just had to switch out an ORM and it was a relatively daunting task, becau
ID: 642131 • Letter: I
Question
I've just had to switch out an ORM and it was a relatively daunting task, because the query logic was leaking everywhere. If i'd ever had to develop a new application, my personal preference would be to encapsulate all query logic (using an ORM) to futureproof it for change. Repository pattern is quite troublesome to code and maintain so i was wondering if there are any other patterns to solve the problem ?
I can foresee posts about not adding extra complexity before it's actually needed, being agile etc. but i'm only interested about the existing patterns solving a similar problem in a simpler way.
My first thought was to have a generic type repository, to which i add methods as needed to specific type repository classes via extension methods, but unit testing static methods is awfully painful. IE:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
Explanation / Answer
First of all: A generic repository should be considered to be a base class and not complete implementations. It should help you to get the common CRUD methods in place. But you still have to implement the query methods:
public class UserRepository : EntityFrameworkRepository<User>, IUserRepository
{
public UserRepository(DbContext context){}
public ICollection<Person> FindRetired()
{
return context.Persons.Where(p => p.Status == "Retired").ToList();
}
}
Second:
Do not return IQueryable. It's a leaky abstraction. Try to implement that interface yourself or use it without knowledge about the underlying db provider. For instance, every db provider has it's own API for eagerly load entities. That's why it's a leaky abstraction.
Alternative
As an alternative you can use queries (for instance as defined by the Command/Query separation pattern). CQS is described in wikipedia.
You basically create query classes which you invoke:
public class GetMyMessages
{
public GetMyMessages(IDbConnection connection)
{
}
public Message[] Execute(DateTime minDate)
{
//query
}
}
the great thing with queries is that you can use different data access methods for different queries without cluttering the code. you can for instance use a web service in one, nhibernate in another and ADO.NET in a third.
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.