gpt4 book ai didi

nhibernate - 使用 NHibernate 正确映射多态关系

转载 作者:行者123 更新时间:2023-12-03 23:36:20 25 4
gpt4 key购买 nike

我正在尝试使用 NHibernate 2.0.1 创建一个 table-per-hierarchy 映射。
我有一个基类,其中包含其他类继承的每个子类的属性。所有这些对象都保存在一个名为 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>

我收到一个错误查询,说无法将鉴别器值格式化为实体 NS.Core.Model.BaseMessage 的 SQL 字符串,所以我在这个类上放置了一个鉴别器值,但它不应该返回基类。这导致我出现了一些 antlr 错误。

我对这个问题采取了错误的方法吗?我想查询表并获取所有从基类继承的不同 POCO 的列表。它永远不会返回基类本身。

下面是 BaseMessage.cs
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;

namespace NS.Core.Model
{

[Serializable]
[DataContract]
[KnownType(typeof(User))]
public class BaseMessage
{
#region Private variables
private long _messageID;
private DateTime? _dateCreated;
private DateTime? _datePublished;
private int _sourceID;
private User _user = new User();

#endregion

#region Properties
[DataMember]
public virtual long MessageID
{
get { return _messageID; }
set { this._messageID = value; }
}
[DataMember]
public virtual DateTime? DateCreated
{
get { return _dateCreated; }
set { this._dateCreated = value; }
}
[DataMember]
public virtual DateTime? DatePublished
{
get { return _datePublished; }
set { this._datePublished = value; }
}
[DataMember]
public virtual int SourceID
{
get { return _sourceID; }
set { this._sourceID = value; }
}
[DataMember]
public virtual User User
{
get
{
if (this._user != null)
{ return this._user; }
else { return new User(); }
}
set { this._user = value; }
}
#endregion
}
}

最佳答案

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

您可以在代码中明确指出 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>

另外,我看到您已将一个属性映射到鉴别器列。相反,您应该拥有一个返回类独有内容的方法 - 在本例中为代码。

请注意,您无法在保存映射实体后更改其类。甚至不是通过改变鉴别器。如果您确实通过 SQL 更改了它,那么您的二级缓存仍将保留具有原始类的版本。
class BaseMessage
{
public virtual string MessageType { return null; }
}

class NMessage : BaseMessage
{
public override string MessageType { return "NMessage"; }
}

最后,您的映射文件过于冗长,因为它包含默认值。可以删除以下属性和元素:
  • access="property"- 这是默认值
  • type="String"- 你使用的所有类型都可以从你的 .NET 类中推断出来
  • column="COL"- 默认与名称相同
  • 类似的 id 列元素

  • 您的所有 Message 子类都具有属性 Body,因此将其移至基类映射。如果此字段可以比您的数据库 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>

    关于nhibernate - 使用 NHibernate 正确映射多态关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2291164/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com