如何使用每个类的层次结构策略管理nhibernate中的多级类层次结构?

时间:2009-06-25 18:46:39

标签: c# nhibernate nhibernate-mapping

我试图在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>

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

2 个答案:

答案 0 :(得分:5)

我对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)

如果我正确解析了代码。点击这个错误时你想做什么?

你是否已经尝试在hibernate-configuration中启用这些功能来检查发生了什么?

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

答案 1 :(得分:2)

afaik Table Per Class表示每个类在DB中获得一个表,从Parent表到继承表的1-1 FK。那时不需要歧视者。 您也不需要映射IActivity(除非您打算将会话直接用于它;然后需要进行一些调整)。

无论如何,我强烈建议您先看一看FluentNHibernate,它会使映射变得非常简单,并且具有非常有用的默认值,可以映射80%而几乎没有任何代码