asp.net-mvcnhibernatedesign-patternsooprepository

How to build a generic repository


I'm developing a web application in ASP.NET MVC with NHibernate.

Based in articles and tutorials I've found at Google, I'm using Repository for my classes.

I have 10 classes and 10 repositories. Today I figured out that 90% of mine repositories are exactly equal each other, except for the class. This is one example:

public class PromocaoRepository:IPromocaoRepository {
    private ISession Session;

    public PromocaoRepository() {
        this.Session = NHibernateSessionFactory.OpenSession();
    }

    public void Add(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Save(promocao);
            transaction.Commit();
        }
    }

    public void Edit(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Update(promocao);
            transaction.Commit();
        }
    }

    public void Remove(Promocao promocao) {
        using(ITransaction transaction = this.Session.BeginTransaction()) {
            this.Session.Delete(promocao);
            transaction.Commit();
        }
    }

    public Promocao GetById(int id) {
        return this.Session.Get<Promocao>(id);
    }

}

There is a way to do a kind of generic repository witch I can use in all my classes?

If it's possible, what should I do in case I need to create a particular method for an specific class?


Solution

  • You should make a generic repository, which you can use in the general case, and if any extra methods is needed for a particular class, add it by using inheritance. Using your example:

    public class GenericRepository<TEntity> :IGenericRepository<TEntity> {
        private ISession Session;
    
        public GenericRepository() {
            this.Session = NHibernateSessionFactory.OpenSession();
        }
    
        public void Add(TEntity instance) {
            using(ITransaction transaction = this.Session.BeginTransaction()) {
                this.Session.Save(instance);
                transaction.Commit();
            }
        }
    
        /* other methods */ 
    }
    
    public class SpecificRepository : GenericRepository<SpecificEntity>, ISpecificRepository 
    {
        public void SpecialQuery()  { /* added method implementation */ }
    }