views:

572

answers:

1

I'm fairly new to NHibernate and have run into a strange inheritance chaining issue with my repository classes. I've been using Gabriel Schenker's FAQ as a reference, and following his examples I've been creating interfaces to define contracts for DAO operations in "repository" classes. The data schema I'm working with is rather extensive, and after a little while I found myself duplicating a lot of code. Specifically, the Add, Update, Delete, and "GetByID" methods were exactly the same after I added a generic "EntityType" parameter to the base interface. So, for example, this would be the most basic interface for repository operations:

public interface IBasicRepository<EntityType> where EntityType : class
{
    void Add(EntityType entity);
    void Remove(EntityType entity);
    void Update(EntityType entity);
    EntityType GetByID<IDType>(IDType id);
}

I'll just talk about the Add method from now on, for the sake of brevity. With the generic EntityType, the implementations were all the same:

public void Add(EntityType entity)
{
    using (ISession session = NHUtility.OpenSession())
    {
         using (ITransaction transaction = session.BeginTransaction())
         {
             session.Save(entity);
             transaction.Commit();
         }
    }
}

Obviously, typing this same method body repeatedly (with the slight change of type) isn't only annoying, it's bad design in my book. So I created an abstract base class I'll call RepositoryBase which provides the implementation for Add(). Since I'm using an abstract instead of an interface, I "break the interface chain" for classes inheriting from RepositoryBase and am forced to make any derivation abstract as well, even though it seems more "correct" to use an interface. Using this crappy little entity example....

public class Entity1
{
    public Guid ID { get; set; }
    public String Name { get; set; }
}

...one can't do this...

public interface IEntity1Repository : RepositoryBase<Entity1>
{
    //Illegal!!!!  Bad, naughty programmer!
}

...but this is fine....

public abstract class Entity1RepositoryBase : RepositoryBase<Entity1>
{
    public abstract ICollection<Entity1> GetByName(string name);
}

This just bothers me. It works, but it rubs me the wrong way, especially as the chain of inheritance/implementation with this particular schema could go quite deep. So I guess my questions are:

  1. Am I just being stupid and anal retentive about this?
  2. Is there a different/better design that I should be looking at here? I've looked at some other examples (notably Billy McCafferty's) and Schenker's approach seems simplest for novice NHibernating.

Thanks in advance.

+6  A: 

One option could be:

public interface IRepository<T> where T: class
{
    void Add(T entity);
    void Remove(T entity);
    void Update(T entity);
    T GetByID<IDType>(IDType id);
}

With a base class that implements that interface. Ie:

public abstract class RepositoryBase<T> : IRepository<T> where T: class
{
    ...
}

Which is then extended for each type of entity if necessary:

public interface IProductRepository :  IRepository<Product>
{
    // Add extra methods
}

public class ProductRepository : RepositoryBase<Product>, IProductRepository 
{
    // Implement extra methods
}
gcores
Yep, that's it. Thanks for untangling me. I was banging my head against the keyboard in confusion.
AJ