【问题标题】:Mixing Inheritance and Tree Structure with Fluent nHibernate使用 Fluent nHibernate 混合继承和树结构
【发布时间】:2010-02-28 09:33:46
【问题描述】:

我正在设计的模型的一部分是层次结构地理位置。由于有多个层并共享一些信息,我决定使用这样的类层次结构:

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,而不是适当的子类。因此,例如,如果我得到 Region 节点并且它的父节点应该是 Country 节点,我无法将 ParentNode 转换为 Country 类。

有没有办法强制 nHibernate 实例化 ParentNode 和 Child 对象及其适当的子类?此信息存储在 Type 列中,因此 nHibernate 实例化正确的子类似乎是合理的。

这里使用继承还有什么大问题吗?使用类层次结构减少了代码量(至少在模型中),但我担心拥有这些隐式而不是显式的关系(例如,一个地区的父级总是一个国家)可能会让我以后遇到麻烦.. .

谢谢!

【问题讨论】:

  • 对于任何关心的人:ActiveRecord 中似乎正确处理了继承,即父/子节点使用正确的子类实​​例化,因此可以正确转换。

标签: nhibernate class inheritance hierarchy fluent


【解决方案1】:

我在我的博客中写过这个: http://mikehadlow.blogspot.com/2010/04/nhibernate-get-vs-load-and-sub-types.html

它包括一个特殊的 Cast 函数,可以正确地转换 NHibernate 代理。

但是,最好的解决方案不是强制转换,而是构建正确的多态代码:)

【讨论】:

    【解决方案2】:

    由于您将其映射为普通引用 nhibernate 在不加载父级的情况下无法知道类型,因此在延迟加载父级时它不知道其类型并创建基类的代理。两种解决方法:

    • 禁用引用的延迟加载:References(x =&gt; x.ParentNode).Not.LazyLoad();
    • 将父类型存储在子记录中:ReferenceAny&lt;(x =&gt; x.ParentNode).TypeColumn("parenttype")... 然后 NH 将创建正确的代理

    我更喜欢选项 1,因为它很简单,通常对性能没有太大意义

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      相关资源
      最近更新 更多