【问题标题】:How to manage a multiple-level class hierarchy in nhibernate with table per class hierarchy strategy?如何在 nhibernate 中使用表每类层次结构策略管理多级类层次结构?
【发布时间】:2009-06-25 18:46:39
【问题描述】:

我正在尝试使用 NHibernate 中的“每个类层次结构表”策略在一个表中实现我的对象层次结构。我的 NHibernate 映射出现错误,可以通过一个简单的示例轻松重现。错误是:

System.NotSupportedException: Attempting to parse a null value into an sql string (column:activity0_.Type).
at NHibernate.SqlCommand.InFragment.ToFragmentString() in InFragment.cs: line 109
at NHibernate.Persister.Entity.SingleTableEntityPersister.DiscriminatorFilterFragment(String alias) in SingleTableEntityPersister.cs: line 551

我可以使用以下域类重现这一点:

public interface IActivity
{
    Guid Id { get; set; }
}

public abstract class Activity : IActivity
{
    public DateTime StartTime { get; set; }
    public Guid Id { get; set; }
}

public class Running : Activity
{
    public string Where { get; set; }
}

public class Talking : Activity
{
    public string ToWhom { get; set; }
}

还有以下 XML 映射:

<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NHibernateTesting"
                   namespace="NHibernateTesting" >
  <class name="IActivity"
         lazy="false"
         table="Activity"
         discriminator-value="0"
         abstract="true">
    <id name="Id">
      <generator class="guid" />
    </id>
    <discriminator column="Type" type="Int16" />
    <subclass name="Activity"
              discriminator-value="1"
              abstract="true"
              lazy="false">
      <property name="StartTime" />
    </subclass>
    <subclass name="Running"
              discriminator-value="2"
              lazy="false"
              extends="Activity">
      <property name="Where" />
    </subclass>
    <subclass name="Talking"
              discriminator-value="3"
              lazy="false"
              extends="Activity">
     <property name="ToWhom" />
    </subclass>
  </class>
</hibernate-mapping>

有人知道我做错了什么吗?

【问题讨论】:

    标签: c# nhibernate nhibernate-mapping


    【解决方案1】:

    我对 c# 和 NHibernate 不太熟悉,但您确定 Activity 应该在映射中设置为 abstract="true" 吗? Activity 类看起来不是抽象的。

    RunningTalking 不应位于 Activity 内,否则将不会保存 StartTime。对吧?

    <subclass name="Activity"
    ...
      <subclass name="Running"
      ...
      </subclass>
      <subclass name="Talking"
      ...
      </subclass>
    ...
    </subclass>
    

    无论如何,错误消息表明 NHibernate 正在尝试使用 in-statement 创建一些查询。但它没有价值。基本上它会尝试像

    ...
    WHERE foo IN (null)
    

    如果我正确解析了代码。当 hit 抛出这个错误时,你想做什么?

    您是否已经尝试在休眠配置中启用这些以检查发生了什么?

    <property name="show_sql">true</property>
    <property name="hibernate.format_sql">true</property>
    <property name="hibernate.use_sql_comments">true</property>
    

    【讨论】:

    • 我认为,这是正确的答案:您需要嵌套子类元素。如果将子类移动到单独的映射文件,则打算使用继承属性。
    • 问题不在于类没有被声明为抽象(虽然很好),但子类没有被嵌套。谢谢你的帮助。这个问题困扰了我好几天。
    【解决方案2】:

    afaik 每类表意味着您在每个类的数据库中获得一个表,从父表到继承表有 1-1 个 FK。那么就不需要歧视者了。 您也不需要映射 IActivity(除非您打算让会话直接针对它工作;然后需要进行一些调整)。

    无论如何,我强烈建议您看看 FluentNHibernate,它使映射变得超级简单,并且具有非常有用的默认值,用于映射 80%,几乎不需要任何代码

    【讨论】:

    • 我指的是每个类 hierarchy 的表,它有一个表用于整个类层次结构。实际上,我确实看过 Fluent NHibernate,但我正在学习它,所以我发现 XML(带有相关手册)要容易得多。我还有一个复杂的对象模型,我必须处理不正常的东西。
    • 如果您还没有这样做的话,最好的选择是咨询 NH 用户组(nhusers @ google 组)。他们在 NH 使用提示方面非常有帮助
    • 我不会切换到 Fluent,因为它们不是 NH 的官方部分,甚至不是贡献包。当 NH 正在发展时,Fluent 将会过时。
    • @Stefan - 我不敢苟同。查看 Hibernate 的历史,映射 API 并没有在一夜之间发生巨大变化。湾。 FluentNH 由大量 NH 用户开发。可以安全地假设他们将使其与任何 NH 开发保持一致 c。即使不是,它也是 OSS,所以如果 NH 引入重大更改,您可以随时拿起它并继续使用 d.即使您不想这样做,并且即使映射 API 发生巨大变化,您也可以始终将当前流畅的映射导出到 hbm(它是单行)并继续使用 xml 路由。失去 Fluent 赋予你的超能力是一个错误 IMO
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 2016-03-27
    • 2011-10-17
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多