views:

163

answers:

1

Part of a model I'm designing is a hierarchy geographic locations. Since there are multiple layers and share some information I decided to use a class hierarchy like this:

public class GeographicNode
{
    public virtual int Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual GeographicNode ParentNode { get; set; }
    public virtual IList<GeographicNode> ChildNodes { get; set; }
}


public class Region : GeographicNode
{
    public virtual int SomeRegionData { get; set; }
}

public class Country : GeographicNode
{
    public virtual int SomeCountryData { get; set; }
}

To map this I'm using a table-per-class-hierarchy method. The Fluent nHibernate mapping looks like this:

public class GeographicNodeMap : ClassMap<GeographicNode>
{
    public GeographicNodeMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        References(x => x.ParentNode);
        HasMany(x => x.ChildNodes).KeyColumn("Id").Cascade.All();

        DiscriminateSubClassesOnColumn("Type");
    }
}

public class RegionMap : SubclassMap<Region>
{
    public RegionMap()
    {
        Map(x => x.SomeRegionData)
    }
}

public class CountryMap : SubclassMap<Region>
{
    public CountryMap()
    {
        Map(x => x.SomeCountryData)
    }
}

Here is my question:

When I get a node and try to access ParentNode (or the children), its type is actually GeographicNode, and not the appropriate subclass. So for example if I get Region node and its parent is supposed to be a Country node, I'm unable to cast ParentNode to Country class.

Is there a way to force nHibernate to instantiate the ParentNode and Child objects with their appropriate subclass? This information is stored in the Type column, so it'd seem reasonable for nHibernate to instantiate the correct subclass.

Also are there any major concerns with using inheritance here? Using a class hierarchy reduces the amount of code (at least in the model), but I'm worried that having these implicit rather than explicit relationships (e.g. the parent of a region is always a country) can get me into trouble later...

Thanks!

A: 

I wrote about this in my blog here: http://mikehadlow.blogspot.com/2010/04/nhibernate-get-vs-load-and-sub-types.html

It includes a special Cast function that correctly casts NHibernate proxies.

However, the best solution is not to cast, but to build correctly polymorphic code :)

Mike Hadlow