public interface IRepository<T> where T : class { void Save(T instance); void Delete(T instance); TResult FindOne<TResult>(ISpecification<T, TResult> specification); IQueryable<TResult> FindAll<TResult>(ISpecification<T, TResult> specification); IQueryable<T> FindAll(); }Your LINQ to SQL repository implementation might look something like this (I’ve snipped a bunch of code and left one method implemented):
public class Repository<T> : IRepository<T> where T : class { private readonly DataContext _ctx; public Repository(DataContext ctx) { _ctx = ctx; } public void Save(T instance) ... public void Delete(T instance) ... public TResult FindOne<TResult>(ISpecification<T, TResult> specification) ... public IQueryable<TResult> FindAll<TResult>(ISpecification<T, TResult> specification) ... public IQueryable<T> FindAll() { return _ctx.GetTable<T>().AsQueryable(); } }The problem is that the call to _ctx.GetTable<T>() expects T to be a type defined in the LINQ to SQL layer – not a data transfer type.
Let’s say you have a User data transfer class. You would expect to instantiate the repository as follows:
var repository = new Repository<User>();This won’t work because the User type would have to be the User type defined in the LINQ to SQL layer. Your client code will no longer be agnostic as to the data access layer.
How rubbish is that!
There are some very hacky workarounds that all involve writing lots of unnecessary code.
See: