views:

48

answers:

2

Hi guys,

Suppose I have a few definitions like so:

public interface ICategory
{
    int ID { get; set; }
    string Name { get; set; }
    ICategory Parent { get; set; }
}

public class Category : ICategory
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual ICategory Parent { get; set; }
}

How do I map such a scenario in NHibernate/EF 4? I am trying to separate the implementation of the DAL.

I am learning NHibernate, EF 4.

Regards, Karan

A: 

NHibernate has issues mapping interfaces to tables.

We've gotten around it by creating a protected variable of the concrete type which is used for mapping, and exposing the interface type as a getter/setter for that concrete type:

// this is mapped to the table
protected virtual Category ConcreteParent { get; set; }

// this is used to access the mapped one
public virtual ICategory Parent 
{ 
    get
    {
        return (ICategory)ConcreteParent;
    } 
    set
    {
        ConcreteParent = (Category)value;
    }
}

(That code is off the top of my head - I'm confident it will have a syntax error hidden in it, but the idea is there).

Its not the prettiest implementation and it feels ugly, but it works. Perhaps someone else will see this and have an alternative :).

Michael Shimmins
This is also what I had come up with... it will probably work fine for simpler properties (like the one above) but for collections it is definitely not optimal.Is there a simpler solution in Entity Framework 4?
KiD0M4N
We use the same approach for collections (ie: children rather than parents). I don't know about EF4 sorry.
Michael Shimmins
I was sort of hoping that NHibernate would be a little more capable in this area. I am looking around for a more technically 'sound' solution.Thanks for the help.
KiD0M4N
Np - I agree with you about the smell this lets off. I'm somewhat hoping that someone might stumble on your question here with a better solution that I can adopt. I've just never been bothered to ask about it myself, and accepted the hacky solution we came up with.
Michael Shimmins
I was trying to expand this approach to work with collections and am stuck atm. If the interface defines a ICollection<IProduct> Products, how would you implement Products in the concrete class?
KiD0M4N
A: 

I was not aware of that problem about hierarchy mapping using NHibernate. However, perhaps you already know if you're reporting this issue, here's how it should be done:

<class name="ICategory" table="Categories">
  <id name="ID" column="IdCategory">
    <generator class="identity">
  </id>
  <property name="Name"/>
  <component name="Parent" class="ICategory"> <!-- class attribute is normally optional -->
    <!-- Here, I would have some test to do to determine whether we have to list the properties -->
    <!-- I would say no and this would makes sense to me, but without having tested it, I can't confirm. -->
  </component>
  <union-subclass="Category">
    ...
  </union-subclass>
</class>

If you're Category object class doesn't provide anymore properties than your interface ICategory, you may put all of the properties within the parent class element, then only declare your subsequent union-subclass object within it.

You may want to consult the NHibernate Reference Documentation, Chapter 8 - Inheritence mapping for further details on the subject. As for component mapping, you want to check Chapter 7 - Component Mapping.

As for EF4, I can't help as I have never already worked with it. Sorry.

Will Marcouiller