Generic Repository: Am I over-complicating? I have created a generic repository for my MVC 3 page. I am using interfaces and a UnitOfWork. But before I set out to do this? Is this the right way to separate my databaseaccess from my viewmodels and views?

WHY I DID IT:

I want to seperate my databaseaccess from my viewmodels and my views, I also want the option to have specific methods for inserting some of my data hence the UserRepository. I also want a controlled environment using the UnitOfWork.

FEARS:

Am I over-complicating everything using these interfaces? Should I ditch the generic repository, I will use it for "basic" inserts so it's not useless by any means. I do understand that I might save some time having the generic repository, only to be creating specific repositories for some of my inserts/update/deletes.

Summary:

It consists of 6 files at the moment of which 2 are:


IRepository
GenericRepository
IUnitOfWork
UnitOfWork
IUserRepository
UserRepository




Code

IRepository:

public interface IRepository&lt;T&gt; where T : class
{
        IEnumerable&lt;T&gt; BaseFetchAll();
        void BaseAdd(T entity);
        void BaseDelete(T Entity);
}


Repository:

public abstract class GenericRepository&lt;T&gt; : IRepository&lt;T&gt; where T : class
{
    private IObjectSet&lt;T&gt; _dbContext;
    private Entities _context;
    protected DbSet&lt;T&gt; dbSet;

    internal GenericRepository(Entities context)
    {
        this._context = context;
        dbSet = context.Set&lt;T&gt;();
    }


    public void BaseDelete(T entity)
    {
        dbSet.Remove(entity);
    }


    public IEnumerable&lt;T&gt; BaseFetchAll()
    {
        return (IEnumerable&lt;T&gt;)(from x in dbSet select x).ToList&lt;T&gt;();
    }

    public void BaseAdd(T entity)
    {
        dbSet.Add(entity);
    }
}


IUnitOfWork:
Before you kick my butt, I am to implement the save,rollback etc. methods this is just to show you what I'm doing.

public interface IUnitOfWork
{  
    IUserRepository UserRepository { get; }
    IUserFileRepository UserFileRepository { get; }
}


UnitOfWork:

public class UnitOfWork : IUnitOfWork
{   
    private IUserRepository _userRepository;
    private Entities context = new Entities();

    public IUserRepository UserRepository
    {
        get
        {
             if(this._userRepository == null)
               this._userRepository = new UserRepository(context);
             return this._userRepository;
        }
    }
}


IUserRepository:

public interface IUserRepository: IRepository&lt;t_users&gt; 
{
    IEnumerable&lt;t_users&gt; FetchAllUsers();
    void InsertToUserTableWithSpecs();        
}


UserRepository:

public class UserRepository : GenericRepository&lt;t_users&gt;, IUserRepository
{

    private Entities dbContext;  
    public UserRepository(Entities context) : base(context) 
    {
        this.dbContext = context;     
    }


    public IEnumerable&lt;t_users&gt; FetchAllUsers()
    {
        return (IEnumerable&lt;t_users&gt;)(from x in dbContext.t_users select x);
    }

    public void InsertToUserTableWithSpecs()
    {

    }
}


Not a lot of code but hopefully something to give you an idea in which direction I'm going.
I think if you are going to have only one Repository, then yeah this is over complicated! But if you will have many Repositories and you will be adding more and more, then you are on the right track. But couple of points: 

I am not sure how your are using your UoW. From my point of view UoW should look like something like: 

interface IUnitOfWork
{
    Begin();
    End();
    Rollback();
}


And UoW should be passed to Repositories. So basically you have a UoW that couple of Repositories may use to get their job done (get/insert records for instance). From where I look at this a UoW is not specific to a single Repository and can span multiple Repositories. 

Imagine for instance that your UoW involves creating an Order entity and updating the Customer entity together. 

Also I would suggest to tighten IRepository definition to:

public interface IRepository&lt;T&gt; where T : IDomainObject


This basically is saying that repositories are not supposed to be created for any sort of class. Your Domain classes can then implement IDomainObject to satisfy this condition. IDomainObject can be empty or depending on your Domain it can have some Domain related properties.