使用 NHibernate 从连接子类加载基类中的集合

发布于 2024-12-04 16:17:31 字数 2277 浏览 0 评论 0原文

我有一个具有一些属性和名称集合的类,如下所示:

public class A : BaseObject
{
    private Int32 zindex;
    private Int32 atNmNr;
    private IList<G020_Namen> names = new List<G020_Namen>();
}

然后我有一个类 B,它扩展了类 A,如下所示:

public class B : A
{
    private Int32 zindex;
    private String etiketnaam;

    public B() { }

    public virtual Int32 Zindex
    {
        get { return zindex; }
        set { zindex = value; }
    }
}

A 和 B 在其主键上链接。 B 类作为连接子类映射到 A 类的映射文件中,如下所示:

    <class name="A" table="A" lazy="true" >
<cache usage="read-write"/>
<id name="Zindex" type="Int32" >
  <column name="Zindex" />
  <generator class="assigned" />
</id>
<property name="AtNmNr" type="Int32">
  <column name="ATNMNR"/>
</property>
<bag name="Namen" table="G020_Namen" inverse="true" cascade="all-delete-orphan" fetch="select" lazy="false" >
  <cache usage="read-write"/>
  <key>
    <column name="NMNR" />
  </key>
  <one-to-many class="G020_Namen" />
</bag>
<joined-subclass name="B" table="B" >
  <key column="Zindex" />
  <property name="Zindex" type="Int32">
    <column name="Zindex"/>
  </property>
  <property name="Etiketnaam" type="String">
    <column name="Etiketnaam"/>
  </property>
</joined-subclass>

现在,如果我想使用 Criteria 检索 A 的记录,它可以正常工作并且名称集合已加载。但是,如果我想检索子类 B 的记录,则不会加载名称集合(在基类 A 上)。

然后,我尝试添加 CreateCriteria 来映射集合:

        ICriteria crit = session.CreateCriteria(typeof(B))
            .CreateCriteria("Names", NHibernate.SqlCommand.JoinType.InnerJoin);

它会产生以下 SQL:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON B.Zindex = G020_Namen.NMNR

因此它尝试将具有名称的表链接到子类表 B 的主键,而不是链接到基表 A 的外键应该是:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON A.AtNnNr = G020_Namen.NMNR

问题是:是否可以使 NHibernate 使用 ICriteria 语句从子类加载基类上的集合?

谢谢,

Martin van der Linden。

I have a class with some properties and a collection of names like so:

public class A : BaseObject
{
    private Int32 zindex;
    private Int32 atNmNr;
    private IList<G020_Namen> names = new List<G020_Namen>();
}

Then I have a class B that extends class A like so:

public class B : A
{
    private Int32 zindex;
    private String etiketnaam;

    public B() { }

    public virtual Int32 Zindex
    {
        get { return zindex; }
        set { zindex = value; }
    }
}

A and B are linked on their primary keys. Class B is mapped in the mapping file of class A as a joined-subclass like so:

    <class name="A" table="A" lazy="true" >
<cache usage="read-write"/>
<id name="Zindex" type="Int32" >
  <column name="Zindex" />
  <generator class="assigned" />
</id>
<property name="AtNmNr" type="Int32">
  <column name="ATNMNR"/>
</property>
<bag name="Namen" table="G020_Namen" inverse="true" cascade="all-delete-orphan" fetch="select" lazy="false" >
  <cache usage="read-write"/>
  <key>
    <column name="NMNR" />
  </key>
  <one-to-many class="G020_Namen" />
</bag>
<joined-subclass name="B" table="B" >
  <key column="Zindex" />
  <property name="Zindex" type="Int32">
    <column name="Zindex"/>
  </property>
  <property name="Etiketnaam" type="String">
    <column name="Etiketnaam"/>
  </property>
</joined-subclass>

Now if I want to retrieve records for A using Criteria it works fine and the collection of names is loaded. But if I want to retrieve records for the subclass B the collection of names is not loaded (on the base class A).

I then tried to add a CreateCriteria to map the collection:

        ICriteria crit = session.CreateCriteria(typeof(B))
            .CreateCriteria("Names", NHibernate.SqlCommand.JoinType.InnerJoin);

It results in the following SQL:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON B.Zindex = G020_Namen.NMNR

So it is trying to link the table with the names to the primary key of the subclass table B instead of to the foreign key of the base table A. It should be:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON A.AtNnNr = G020_Namen.NMNR

The question is: Is it possible to make NHibernate load a collection on a base class from the subclass with ICriteria statements?

Thanks,

Martin van der Linden.

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

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

发布评论

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

评论(1

萝莉病 2024-12-11 16:17:31

您的期望不正确:

内连接 G020_Namen ON A.AtNnNr = G020_Namen.NMNR

AtNnNr 甚至未映射。如果您指的是 ATNMNR,则不应在连接中使用它,因为它是一个没有 FK 的简单列。请添加有关原始问题的更多信息:

但是如果我想检索子类 B 的记录
未加载名称(在基类 A 上)。

什么没有加载?名字还是B?没加载怎么办?异常还是空集合?

顺便说一句,您的映射并不是最佳的。

  • 看起来您希望立即加载集合 (lazy="false")。在这种情况下,请使用 fetch="join" 而不是 fetch="select" 以避免额外的 SELECT。

  • 您不需要在 B 类上使用 。如果您使 zindex 受到保护,您可以从基类中获取它。

Your expectation are incorrect:

INNER JOIN G020_Namen ON A.AtNnNr = G020_Namen.NMNR

AtNnNr is not even mapped. If you meant ATNMNR than it should not be used in join because it is a simple column without FK. Please add more information on the original problem:

But if I want to retrieve records for the subclass B the collection of
names is not loaded (on the base class A).

What is not loaded? Names or Bs? Not loaded how? Exception or empty collection?

As a side note, your mapping is not optimal.

  • Looks like you want your collection to be loaded eagerly (lazy="false"). In this case, use fetch="join" instead of fetch="select" to avoid additional SELECT.

  • You don't need <property name="Zindex" type="Int32"> on class B. You can get this from the base class if you make zindex protected.

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