正确映射与NHibernate的多态性关系

正确映射与NHibernate的多态性关系,nhibernate,nhibernate-mapping,polymorphism,Nhibernate,Nhibernate Mapping,Polymorphism,我正在尝试使用NHibernate2.0.1创建每个层次的表映射。 我有一个基类,它的属性存在于其他类继承的每个子类中。所有这些对象都被持久化到一个名为Messages的表中,该表包含每个类的所有可能字段。有一个SourceID,它是鉴别器,应该指示每个子类返回哪个Poco。这是我当前的映射 <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

我正在尝试使用NHibernate2.0.1创建每个层次的表映射。 我有一个基类,它的属性存在于其他类继承的每个子类中。所有这些对象都被持久化到一个名为Messages的表中,该表包含每个类的所有可能字段。有一个SourceID,它是鉴别器,应该指示每个子类返回哪个Poco。这是我当前的映射

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="NS.Core"
                   namespace="NS.Core.Model">
  <class name="BaseMessage" table="Messages">
    <id name="MessageID" type="Int64">
      <column name="MessageID" />
      <generator class="native" />
    </id>
    <discriminator column="SourceID" type="Int32"/>
    <property name="DateCreated" access="property" column="DateCreated" type="DateTime" not-null="true"/>
    <property name="DatePublished" access="property" column="DatePublished" type="DateTime"/>
    <property name="SourceID" access="property" column="SourceID" type="Int32"/>
    <many-to-one name="User" column="UserID" access="property" cascade="none" lazy="false" fetch="join" outer-join="true" />
    <subclass name="NMessage" discriminator-value="0">
      <property name="Body" access="property" column="Body" type="String"/>
    </subclass>
    <subclass name="BMessage" discriminator-value="1">
      <property name="Title"  access="property" column="Title" type="String"/>
      <property name="Body" access="property" column="Body" type="String"/>
    </subclass>
    <subclass name="CMessage" discriminator-value="2">
      <property name="Url"  access="property" column="Url" type="String"/>
      <property name="Body" access="property" column="Body" type="String"/>
    </subclass>
  </class>
</hibernate-mapping>

方法是合理的。我已经做过好几次了

您可以在代码中显式地保护BaseMessage的默认构造函数

您还需要在基类上声明一个鉴别器值

我喜欢使用字符串值作为鉴别器,因为这样在执行SQL查询或报告时更清晰。此外,由于BaseMessage的实例不存在,in将使用null作为其鉴别器值

<class name="BaseMessage" table="Messages" discriminator-value="null">
    <id />
    <discriminator column="SourceID" />
    <subclass name="NMessage" discriminator-value="NMessage">
    </subclass>
    <subclass name="BMessage" discriminator-value="BMessage">
    </subclass>
    <subclass name="CMessage" discriminator-value="CMessage">
    </subclass>
</class>
最后,映射文件过于冗长,因为它包含默认值。可以删除以下属性和元素:

  • access=“property”-这是默认设置
  • type=“String”-可以从.NET类推断出您使用的所有类型
  • column=“COL”-默认值与名称相同
  • 对于id列元素也是如此
所有消息子类都有属性体,因此将其移动到基类映射。如果此字段可以比数据库varchar长,则它应该是一个文本列,并具有type=“StringCLob”映射到.NET中的字符串

<class name="BaseMessage" table="Messages" discriminator-value="null">
    <id name="MessageID">
        <generator class="native" />
    </id>
    <discriminator column="SourceID"/>
    <property name="DateCreated" />
    <property name="DatePublished" />
    <many-to-one name="User" column="UserID" cascade="none" lazy="false" fetch="join" outer-join="true" />
    <property name="Body" type="StringCLob" />
    <subclass name="NMessage" discriminator-value="NMessage">
    </subclass>
    <subclass name="BMessage" discriminator-value="BMessage">
        <property name="Title" />
    </subclass>
    <subclass name="CMessage" discriminator-value="CMessage">
        <property name="Url" />
    </subclass>
</class>


您可以发布BaseMessage的代码吗?如果数据库不包含BaseMessage的SourceID(该ID从未存储在数据库中),该怎么办?作为映射类,它需要一个鉴别器值。这样一个值永远不会存在是应用程序级验证逻辑。这是一个简洁的示例,并不是每个示例中都有正文,但您的响应使它起到了作用。谢谢
class BaseMessage
{
    public virtual string MessageType { return null; }
}

class NMessage : BaseMessage
{
    public override string MessageType { return "NMessage"; }
}
<class name="BaseMessage" table="Messages" discriminator-value="null">
    <id name="MessageID">
        <generator class="native" />
    </id>
    <discriminator column="SourceID"/>
    <property name="DateCreated" />
    <property name="DatePublished" />
    <many-to-one name="User" column="UserID" cascade="none" lazy="false" fetch="join" outer-join="true" />
    <property name="Body" type="StringCLob" />
    <subclass name="NMessage" discriminator-value="NMessage">
    </subclass>
    <subclass name="BMessage" discriminator-value="BMessage">
        <property name="Title" />
    </subclass>
    <subclass name="CMessage" discriminator-value="CMessage">
        <property name="Url" />
    </subclass>
</class>