使用 NHibernate 从连接子类加载基类中的集合
我有一个具有一些属性和名称集合的类,如下所示:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的期望不正确:
AtNnNr 甚至未映射。如果您指的是 ATNMNR,则不应在连接中使用它,因为它是一个没有 FK 的简单列。请添加有关原始问题的更多信息:
什么没有加载?名字还是B?没加载怎么办?异常还是空集合?
顺便说一句,您的映射并不是最佳的。
看起来您希望立即加载集合 (
lazy="false"
)。在这种情况下,请使用fetch="join"
而不是fetch="select"
以避免额外的 SELECT。您不需要在 B 类上使用
。如果您使 zindex 受到保护,您可以从基类中获取它。Your expectation are incorrect:
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:
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, usefetch="join"
instead offetch="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.