我试图让NHibernate基于3个表的内部联接做一个简单的查询:
var sessionCriteria = session.CreateCriteria<FoobarMaster>("M")
.CreateCriteria("Accounts", "A", NHibernate.SqlCommand.JoinType.InnerJoin)
.CreateCriteria("TrackingRecords", "T", NHibernate.SqlCommand.JoinType.InnerJoin)
.Add(Restrictions.Eq("T.PicNumber", "123456"));
var foobarMaster = sessionCriteria.UniqueResult<FoobarMaster>();
而在LINQ中,同样的事情:
from m in session.Query<FoobarMaster>()
from a in m.Accounts
from t in a.TrackingRecords
where t.PicNumber == "12345"
select m
使用QueryOvers和JoinAliases我也有同样的想法。总体而言,我遇到了运行时异常:
“无法解析属性:TrackingNo of:帐户”。
奇怪的TrackingNo
是,它是一个TrackingRecord
属性而不是一个Account属性。它甚至以T为前缀-的别名TrackingRecord
。
这是我的映射:
<class name="FoobarMaster" table="T_FOOBAR_MASTER">
<id name="FoobarMasterId" column="FOOBAR_MASTER_ID" type="int">
<generator class="identity"/></id>
<bag name="Accounts" cascade="all" inverse="true">
<key column="FOOBAR_MASTER_ID" />
<one-to-many class="FoobarAccount" />
</bag>
...
<class name="FoobarAccount" table="T_FOOBAR_ACCOUNT">
<id name="FoobarAccountId" column="FOOBAR_ACCOUNT_ID" type="int">
<generator class="identity"/></id>
<many-to-one name="FoobarMaster" class="FoobarMaster" column="FOOBAR_MASTER_ID" />
<property name="AccountId" column="ACCOUNT_ID" />
<bag name="TrackingRecords" cascade="all" inverse="true">
<key column="ACCOUNT_ID" />
<one-to-many class="FoobarAccount" />
</bag>
...
<class name="TrackingRecord" table="T_TRACKING">
<id name="TrackingId" column="TRACKING_ID" type="int"><generator class="identity"/></id>
<many-to-one name="FoobarAccount" class="FoobarAccount" column="ACCOUNT_ID" />
<property name="PicNumber" column="PICNUMBER" type="AnsiString" length="25" />
...
这是类/实体:
public class FoobarMaster
{
public virtual int FoobarMasterId { get; set; }
public virtual IList<FoobarAccount> Accounts { get; set; }
...
public class FoobarAccount
{
public virtual int FoobarAccountId { get; set; }
public virtual FoobarMaster FoobarMaster { get; set; }
public virtual int AccountId { get; set; }
public virtual IList<TrackingRecord> TrackingRecords { get; set; }
...
public class TrackingRecord
{
public virtual long TrackingId { get; set; }
public virtual FoobarAccount FoobarAccount { get; set; }
public virtual string PicNumber { get; set; }
...
根据最新的问题,这里的答案很清楚,很容易解决!映射包含错误的one-to-many
设置。请参阅第一级列表:
<bag name="Accounts" cascade="all" inverse="true">
<key column="FOOBAR_MASTER_ID" />
<!-- here we can see the CORRECT reference -->
<one-to-many class="FoobarAccount" />
</bag>
另一方面,第二个级别具有相同的目标,这是错误的:
<bag name="TrackingRecords" cascade="all" inverse="true">
<key column="ACCOUNT_ID" />
<!-- WRONG. In deed, the Account does NOT contain 'PicNumber' -->
<one-to-many class="FoobarAccount" />
</bag>
更改<one-to-many class="FoobarAccount" />
成<one-to-many class="TrackingRecord" />
正确的映射应如下所示:
<bag name="TrackingRecords" cascade="all" inverse="true">
<key column="ACCOUNT_ID" />
<!-- now we won't recieve the Account does not contain 'PicNumber' -->
<one-to-many class="TrackingRecord" />
</bag>
从那一刻起,所有东西都将正常工作,问题开头的查询是正确的。无需子查询等
...
如果您的对象/实体像这样被链接起来,那么您尝试实现的目标将起作用
Master
有多个(或引用)帐户Account
有很多(或引用)TrackingRecords但是根据您遇到的问题,似乎您的映射是
Master
有多个(或引用)帐户Master
有很多(或引用)TrackingRecords在这种情况下,您只能实现SQL
select m.* from t_master m
inner join t_account a on m.master_id = a.master_id
//inner join t_tracking t on a.account_id = t.account_id
inner join t_tracking t on m.account_id = t.account_id // the m.account_id
where t.tracking_no = '123456'
查询应该是这样的:
// do some filter over A
var rootQuery = session.CreateCriteria<Master>("M")
.CreateCriteria("Accounts", "A", NHibernate.SqlCommand.JoinType.InnerJoin);
// working with the T here
rootQuery.CreateCriteria("TrackingRecords", "T", NHibernate.SqlCommand.JoinType.InnerJoin)
.Add(Restrictions.Eq("T.TrackingNo", "123456"));
此映射不适合:
TrackingRecords的关键列是ACCOUNT_ID
<class name="Account" table="T_ACCOUNT">
...
<bag name="TrackingRecords" cascade="all" inverse="true">
<key column="ACCOUNT_ID" />
...
虽然TrackingRecord的引用是通过ACCOUNT_NUMBER完成的
<class name="TrackingRecord" table="T_TRACKING">
...
<many-to-one name="Account" class="Account" column="ACCOUNT_NUMBER" />
...
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句