Смешение наследования и древовидной структуры с помощью Fluent nHibernate

Часть модели, которую я разрабатываю, представляет собой иерархию географических местоположений. Поскольку существует несколько слоев и имеется некоторая информация, я решил использовать такую ​​иерархию классов:

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; }
}

Чтобы отобразить это, я использую метод иерархии «таблица на класс». Отображение Fluent nHibernate выглядит так:

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)
    }
}

Вот мой вопрос:

Когда я получаю узел и пытаюсь получить доступ к ParentNode (или дочерним узлам), его тип на самом деле является GeographicNode, а не соответствующим подклассом. Так, например, если я получаю узел региона, а его родительский узел должен быть узлом страны, я не могу преобразовать ParentNode в класс страны.

Есть ли способ заставить nHibernate создавать экземпляры объектов ParentNode и Child с их соответствующим подклассом? Эта информация хранится в столбце Тип, поэтому для nHibernate было бы разумно создать экземпляр правильного подкласса.

Также есть ли здесь какие-либо серьезные проблемы с использованием наследования? Использование иерархии классов сокращает объем кода (по крайней мере, в модели), но меня беспокоит, что наличие этих неявных, а не явных отношений (например, родителем региона всегда является страна) может вызвать у меня проблемы позже. .

Спасибо!


person Poya M.    schedule 28.02.2010    source источник
comment
Для всех, кого это волнует: похоже, что наследование правильно обрабатывается в ActiveRecord, то есть родительские / дочерние узлы создаются с правильным подклассом и, следовательно, могут быть правильно преобразованы.   -  person Poya M.    schedule 12.03.2010


Ответы (2)


Я писал об этом в своем блоге здесь: http://mikehadlow.blogspot.com/2010/04/nhibernate-get-vs-load-and-sub-types.html

Он включает специальную функцию Cast, которая правильно выполняет приведение прокси NHibernate.

Однако лучшим решением будет не приведение, а правильное построение полиморфного кода :)

person Mike Hadlow    schedule 15.10.2010

поскольку вы сопоставили его как обычную ссылку, nhibernate не может знать тип с загрузкой родительского элемента, поэтому при ленивой загрузке родительского элемента он не знает его тип и создает прокси-сервер th базового класса. Два варианта исправить это:

  • отключить отложенную загрузку ссылки: References(x => x.ParentNode).Not.LazyLoad();
  • сохранить родительский тип в записи дочернего элемента: ReferenceAny<(x => x.ParentNode).TypeColumn("parenttype")... тогда NH создаст правильный прокси

Я бы предпочел вариант 1, поскольку он прост и обычно не имеет большого значения для производительности

person Firo    schedule 31.08.2012