HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Generic repository pattern

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
patterngenericrepository

Problem

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 in UserController, similarly in other controllers and using repositoryPattern.



Generic Repository Interface

public interface IGenericRepository : IDisposable where T : class
{
    IEnumerable 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
{
private ModelDBEntities dataContext = null;
public UserRepository()
{
this.dataContext = new ModelDBEntities();
}
public UserRepository(ModelDBEntities dataContext)
{
this.dataContext = dataContext;
}

public IEnumerable SelectAll()
{
return dataContext.Users;
}
public User SelectByID(object argId)
{
long userId = long.Parse(argId.ToString());
return dataContext.Users.Single(u => 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

Solution

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, 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 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 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.

Code Snippets

public interface IGenericRepository : IDisposable
{
    IEnumerable<T> 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();
}
public class GenericRepository : IGenericRepository
{
    public GenericRepository()
    {
        blah...  
    }
    public GenericRepository(ModelDBEntities dataContext)
    {
        blah...  
    }

    public IEnumerable<T> 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...  
    }
}
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...
    }
}

Context

StackExchange Code Review Q#69956, answer score: 3

Revisions (0)

No revisions yet.