Generic repository pattern Please have a through look my custom implementation of generic repository pattern and suggest anything I may be lacking.


I am using a generic interface with 6 methods
I'll be using a repository class for each entity type (e.g UserRepository, ProductRepository, StoreRepository) which are not only going to implement the generic interface but also can add additional methods as per the need with respect to each repository class. for example:

UserRepository can add a new method named as CountUsers() which gets called from controller.
ProductRepository can add a new method named as GetExpiredProducts() which gets called from controller.

I am declaring IGenericRepository&lt;User&gt; in UserController, similarly in other controllers and using repositoryPattern.


Generic Repository Interface

public interface IGenericRepository&lt;T&gt; : IDisposable where T : class
{
    IEnumerable&lt;T&gt; SelectAll();
    T SelectByID(object id);
    void Insert(T obj);
    void Update(T obj);
    void Delete(object id);
    void Save();
}


Implementation of Generic Repository Interface

public class UserRepository : IGenericRepository&lt;User&gt;
{
    private ModelDBEntities dataContext = null;
    public UserRepository()
    {
        this.dataContext = new ModelDBEntities();
    }
    public UserRepository(ModelDBEntities dataContext)
    {
        this.dataContext = dataContext;
    }

    public IEnumerable&lt;User&gt; SelectAll()
    {
        return dataContext.Users;
    }
    public User SelectByID(object argId)
    {
        long userId = long.Parse(argId.ToString());
        return dataContext.Users.Single(u =&gt; u.UserId == userId);
    }
    public void Insert(User obj)
    {
       dataContext.Users.AddObject(obj);
    }
    public void Update(User obj)
    {
        if (obj.EntityState == EntityState.Detached)
            dataContext.Users.Attach(obj);
        dataContext.ObjectStateManager.ChangeObjectState(obj, System.Data.EntityState.Modified);            
    }
    public void Delete(object argUserId)
    {
        long userId = long.Parse(argUserId.ToString());
        dataContext.Users.Single(u =&gt; u.UserId == userId).Status = "inactive";
    }
    public void Save()
    {
        dataContext.SaveChanges();
    }

    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                dataContext.Dispose();
            }
        }
        this.disposed = true;
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}


My User Controller

public class UserController : Controller
{
    private IGenericRepository&lt;User&gt; _repositoryUser = null;     
    public UserController()
    {
        _repositoryUser = new UserRepository();
    }
    public UserController(IGenericRepository&lt;User&gt; repository)
    {
        _repositoryUser = repository;
    }

    [HttpPost]
    public JsonResult SubmitHandler(User argUser)
    {
        if (ModelState.IsValid)
        {
            _repositoryUser.Insert(argUser);
            _repositoryUser.Save();
            return Json("success");
        }
        else
            return Json("failure");
    }
    public ActionResult Delete(object Id)
    {
            if (Id != null &amp;&amp; Id.ToString().Trim().Length &gt; 0)
            {
                int param = int.Parse(Id.ToString());
                _repositoryUser.Delete(Id as object);
                _repositoryUser.Save();
                return View("User", _repositoryUser.SelectAll());
            }
            else
                return View("404");
    }
}
I have created generic repositories many times and what I found was that you're going to need to create interfaces for each entity typed repository.
So IUserRepository that implements IGenericRepository&lt;User&gt;, this way you'll be able to

Inject the repository easier with Inversion Of Control
Create extra methods for each entity type as and when
Test your controller easier

Update
I realise this update comes a long time after the question, but time has past and experience has been gained.
You don't necessarily need a new interface for entity type. IoC containers can inject a specific implementation based on the generic parameter of the IGenericRepositoy interface. You will need an interface however for each implementation that has specific methods for that type, such as GetExpiredProducts() as mentioned in the initial question.
You could also remove the generic parameter from the interface and move the where clause to each method:
public interface IGenericRepository : IDisposable
{
    IEnumerable&lt;T&gt; SelectAll() where T : class;
    T SelectByID(object id) where T : class;
    void Insert(T obj) where T : class;
    void Update(T obj) where T : class;
    void Delete(object id);
    void Save();
}

then implement a GenericRepository class:
public class GenericRepository : IGenericRepository
{
    public GenericRepository()
    {
        blah...  
    }
    public GenericRepository(ModelDBEntities dataContext)
    {
        blah...  
    }

    public IEnumerable&lt;T&gt; SelectAll() where T : class
    {
        blah...  
    }
    public T SelectByID(object argId) where T : class
    {
        blah...  
    }
    public void Insert(T obj) where T : class
    {
       blah...  
    }
    public void Update(T obj) where T : class
    {
        blah...            
    }
    public void Delete(object argId)
    {
        blah...  
    }
    public void Save()
    {
        blah...  
    }
}

this would mean that any implementation of a type specific repository could just inherit this saving you some work
public interface IUserRepository : IGenericRepository
{
    int CountUsers();
}

public class UserRepository : GenericRepository, IUserRepository
{
    public UserRepository()
    {
        blah...  
    }
    public UserRepository(ModelDBEntities dataContext)
        : base(dataContext)
    {
        blah...  
    }
    
    public int CountUsers()
    {
        blah...
    }
}

You can then decide on what you want to inject into your controller, if you just want the base CRUD methods then you will only need to pass in the implementation of IGenericRepository and use for several types.