流畅的NHibernate - 混合table-per-subclass和table-per-class-hierarchy

时间:2011-04-20 21:34:44

标签: fluent-nhibernate joined-subclass table-per-hierarchy

提供以下结构,

MyBaseClass {
  public int Id {get; private set;}
}

MySubclassWithDiscriminator : MyBaseClass {
}

MySubclass : MyBaseClass {
  public string SomeThing {get; set;}
}

我如何使用Fluent NH正确映射这些,使用table-per-subclass和table-per-class-hierarchy?我已经尝试过自定义AutomappingConfiguration,但似乎是在圈子中进行:

public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        return type.Namespace.Contains("Entities");
    }

    public override bool IsDiscriminated(Type type)
    {
        // only classes with additional properties should be 
        // using the table-per-subclass strategy
        if ((type.IsAssignableFrom(typeof(MyBaseClass)) || 
             type.IsSubclassOf(typeof(MyBaseClass)) && 
             type.GetProperties(BindingFlags.Public | 
                                BindingFlags.FlattenHierarchy)
             .Count() <= 1))
        {
            return true;
        }
        return false;
    }
}

public class SubclassConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        // Use the short name of the type, not the full name
        instance.DiscriminatorValue(instance.EntityType.Name);
    }
}

在我的调查中,我认为在使用FNH时使用Discriminator是一个二元选择,而HBM可以同时拥有Discriminator列和子类。

1 个答案:

答案 0 :(得分:0)

编辑 - 2011-05-12

我重写了这篇文章,试图解决詹姆斯格雷戈里的评论。

这是我想要实现的HBM:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class 
   xmlns="urn:nhibernate-mapping-2.2" 
   name="Mixed_Parent" 
   abstract="true" 
   table="`Mixed_Parent`">
    <id name="Id" type="System.Int32">
      <generator class="identity" />
    </id>
    <discriminator type="String">
      <column name="discriminator" />
    </discriminator>
    <subclass 
     name="Mixed_TPCH_Child" 
     discriminator-value="Mixed_TPCH_Child" />
    <subclass 
     name="Mixed_TPS_Child" 
     discriminator-value="Mixed_TPS_Child">
      <join table="`Mixed_TPS_Child`" >
        <key column="Id" />
        <property name="Description" type="String">
          <column name="Description" />
        </property>
      </join>
    </subclass>
  </class>
</hibernate-mapping>

所以,我所看到的是,生成的HBM是<joined-subclass><subclass>没有<join>子元素,而不是两者的组合。我在这里错过了什么吗?

这是一个失败的测试,可以添加到SubclassPersistenceModelTests来说明:

namespace MixedTablePerSubclassWithTablePerClassHierarchy
{
    public class Mixed_Parent
    {
        public virtual int Id { get; set; }
    }

    public class Mixed_TPCH_Child
    {

    }

    public class Mixed_TPS_Child
    {
        public virtual string Description { get; set; }
    }

    public class Mixed_ParentMap : ClassMap<Mixed_Parent>
    {
        public Mixed_ParentMap()
        {
            Id(x => x.Id);
            DiscriminateSubClassesOnColumn("discriminator");
        }
    }

    public class Mixed_TPCH_ChildMap : SubclassMap<Mixed_TPCH_Child>
    { }

    public class Mixed_TPS_ChildMap : SubclassMap<Mixed_TPS_Child>
    {
        public Mixed_TPS_ChildMap()
        {
            Map(x => x.Description);
        }
    }
}

[Test]
public void ShouldAllowMixedTablePerSubclassWithTablePerClassHierarchy()
{
    var model = new PersistenceModel();

    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_ParentMap());
    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_TPCH_ChildMap()
    );
    model.Add(
        new MixedTablePerSubclassWithTablePerClassHierarchy
            .Mixed_TPS_ChildMap());

    var classMapping = model.BuildMappings()
        .First()
        .Classes.First();

    // WHAT SHOULD THIS NUMBER BE (0, 1 or 2)?
    classMapping.Subclasses.Count().ShouldEqual(1);
    classMapping
        .Subclasses
        .First()
        .Type
        .ShouldEqual(
            typeof(
                MixedTablePerSubclassWithTablePerClassHierarchy
                .Mixed_TPS_Child)
        ); // WHICH OF THE CHILDREN WOULD BE FIRST?
}