I've seen some tutorials and examples of implementing a repository pattern, and I don't quite understand something. My impression was that the whole point of a repository pattern was to hide the underlying data storage implementation from the calling code. Am I wrong in this assumption, in which case, what is the point of a repository pattern?
Assuming repositories are meant to hide the underlying implementation, am I right in thinking that implementations like the following EF implementation are leaking EF implementation details and are therefore incorrect repository implementations?
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
// This method was not in the videos, but I thought it would be useful to add.
TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
As I see it, this leaks the fact that EF entities are being used to store and retrieve data from the DB as TEntity
is passed in and returned to and from methods. I'd have thought you'd need to define POCOs, pass them in to the repo, then map then to TEntity
s to be correct. Even more leaky is the Expression<Func<TEntity, bool>> predicate
lambda, which not only leaks TEntity
again but assumes that the underlying implementation implements EF-style .Where()
LINQ queries on datasets. This just seems like it's not decoupled from EF.
Am I misunderstanding the purpose of a repository or are my criticisms valid here?
TEntity
has the word 'Entity' in it, what makes you feel that Entity Framework details are being leaked here? The way the code is written,TEntity
can be any class, and implementors of IRepository can use any data access mechanism they want; it doesn't have to be EF.TEntity
in your code example with justT
. The functionality would not change, but it would be clearer that the IRepository interface is generic and not EF-specific at all. Now, if you are just going to use it to pass EF entities back and forth, that's a different issue. But the IRepository interface itself is agnostic of what kind of classT
is, and doesn't leak actual implementation details that I can see.where TEntity : class
explicitly allows TEntity to represent any class, including EF classes or POCOs or whatever. If you want to limit what kind of class is handled by the interface, change it towhere TEntity : somethingelse