Fluent NHibernate - 混合每个子类表和每个类层次结构表

发布于 2024-11-02 07:37:55 字数 1340 浏览 3 评论 0原文

给出以下结构,

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

MySubclassWithDiscriminator : MyBaseClass {
}

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

我将如何使用 Fluent NH 结合使用每个子类表和每个类层次结构表来正确映射这些结构?我尝试过自定义 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 时,鉴别器的使用是一种二元选择,而 HBM 能够拥有鉴别器列和同时是一个子类。

Give the following structure,

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

MySubclassWithDiscriminator : MyBaseClass {
}

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

How would I use Fluent NH to map these correctly, using a combination of table-per-subclass and table-per-class-hierarchy? I've tried a custom AutomappingConfiguration, but seem to be going around in circles:

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

It seems to me from my investigation that the use of the Discriminator is a binary choice when using FNH, while an HBM has the ability to have a Discriminator column and a subclass at the same time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笔芯 2024-11-09 07:37:55

编辑 - 2011-05-12

我重写了这篇文章以尝试解决 James Gregory 的评论。

这是我试图实现的 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 是 code> 没有 子元素,绝不是两者的组合。我在这里错过了什么吗?

这是一个失败的测试,可以将其添加到 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?
}

EDIT - 2011-05-12

I rewrote this post to try to address James Gregory's comments.

Here's the HBM that I'm trying to achieve:

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

So, what I've seen is that the HBM that's generated is EITHER a <joined-subclass> or <subclass> without the <join> sub-element, never a combination of the two. Am I missing something here?

Here's a failing test that can be added to the SubclassPersistenceModelTests to illustrate:

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?
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文