Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/installation/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NHibernate多个内部联接选择_Nhibernate_Nhibernate Mapping_Nhibernate Criteria - Fatal编程技术网

NHibernate多个内部联接选择

NHibernate多个内部联接选择,nhibernate,nhibernate-mapping,nhibernate-criteria,Nhibernate,Nhibernate Mapping,Nhibernate Criteria,我试图让NHibernate根据3个表的内部联接执行一个简单的查询: var sessionCriteria = session.CreateCriteria<FoobarMaster>("M") .CreateCriteria("Accounts", "A", NHibernate.SqlCommand.JoinType.InnerJoin) .CreateCriteria("TrackingRecords", "T", NHibernate.SqlCommand.JoinType

我试图让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>();
以下是类/实体:

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; }
...
公共类FoobarMaster
{
公共虚拟int FoobarMasterId{get;set;}
公共虚拟IList帐户{get;set;}
...
公共类FoobarAccount
{
公共虚拟int FoobarAccountId{get;set;}
公共虚拟FoobarMaster FoobarMaster{get;set;}
公共虚拟int AccountId{get;set;}
公共虚拟IList跟踪记录{get;set;}
...
公共类跟踪记录
{
公共虚拟长跟踪ID{get;set;}
公共虚拟FoobarAccount FoobarAccount{get;set;}
公共虚拟字符串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" />
  <!--  now we won't recieve the Account does not contain 'PicNumber'  -->
  <one-to-many class="TrackingRecord" />
</bag>
// 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"));
var trackRecAccountIdsSubq = DetachedCriteria.For(typeof(TrackingRecord))
                .SetProjection(Projections.Property("AccountId"))
                .Add(
                    Restrictions.Eq("TrackingNo", "123456")); 

var accountMasterIdsSubq = DetachedCriteria.For(typeof(Account))
                .SetProjection(Projections.Property("MasterId"))
                .Add(
                    Subqueries.PropertyIn("AccountId", trackRecAccountIds)); 

var mastersByTrackRecNoCriteria = session.CreateCriteria<Master>()
                .Add(
                    Subqueries.PropertyIn("MasterId", accountMasterIdsSubq);

var mastersByTrackRecNo = mastersByTrackRecNoCriteria.List<Master>();
//对一个
var rootQuery=session.CreateCriteria(“M”)
.CreateCriteria(“Accounts”、“A”、NHibernate.SqlCommand.JoinType.InnerJoin);
//在这里和T一起工作
CreateCriteria(“TrackingRecords”、“T”、NHibernate.SqlCommand.JoinType.InnerJoin)
.添加(限制条件、等式(“T.TrackingNo”、“123456”);
更新,反映问题扩展: 此映射不匹配:

TrackingRecords的关键列是帐户ID

<class name="Account" table="T_ACCOUNT"> 
...
<bag name="TrackingRecords" cascade="all" inverse="true">
  <key column="ACCOUNT_ID" />
...

...
...
而TrackingRecord的引用是通过账号进行的

<class name="TrackingRecord" table="T_TRACKING">
...
<many-to-one name="Account" class="Account" column="ACCOUNT_NUMBER" />
...

...
...

由于您只通过SQL选择主数据,没有来自T_Account和T_TrackingRecord的字段/列,因此我建议使用DetachedCriteria和子查询

如果您具有TrackingRecord.AccountId和Account.MasterId属性,则可以执行以下操作:

<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>
// 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"));
var trackRecAccountIdsSubq = DetachedCriteria.For(typeof(TrackingRecord))
                .SetProjection(Projections.Property("AccountId"))
                .Add(
                    Restrictions.Eq("TrackingNo", "123456")); 

var accountMasterIdsSubq = DetachedCriteria.For(typeof(Account))
                .SetProjection(Projections.Property("MasterId"))
                .Add(
                    Subqueries.PropertyIn("AccountId", trackRecAccountIds)); 

var mastersByTrackRecNoCriteria = session.CreateCriteria<Master>()
                .Add(
                    Subqueries.PropertyIn("MasterId", accountMasterIdsSubq);

var mastersByTrackRecNo = mastersByTrackRecNoCriteria.List<Master>();
不确定这是否以及如何与实体对象属性(没有外部ID属性)一起工作,但子查询会在数据库上创建快速半联接(理想情况下是通过父实体ID上的索引)


默认情况下,这也只获取主文件,而不是帐户或TrackingRecord;如果您不需要它们,则可以更快地获取。如果您需要它们,并且每个TrackingNo只有一个帐户和主文件,则加入获取可能是更好的选择。

您的LINQ版本运行正常吗?您可以发布您的mappingsLINQ版本吗?我发布了相同的错误我还发布了映射。谢谢。如果没有Erik所描述的分离查询,我认为这是不可能的。我发现如下:。我非常失望。你可以在Ruby on Rails中不费吹灰之力地完成这项工作…@MrTibs只是出于好奇。你看到我的预期答案了吗?你的映射是错误的,因为
TrackingRecords
有一对多
。这就是问题所在。或者您的问题中的代码片段是否仍处于“调整”状态?换句话说,您试图执行的查询是正确的。我测试过,一旦映射正确…我只是好奇;);)谢谢Radim,但我的设置与您在前一个案例中提到的一样。Master有许多帐户,Account有许多TrakcingRecords。我编辑了我的帖子并添加了类和映射。我检查了您的映射,并且至少有一个不一致。请检查它。谢谢捕获。我确实有正确的映射(或者我认为正确的映射是什么),但我在粘贴代码时不得不更改一些变量的名称,因为它们包含产品名称,并且带有商标。我编辑了代码。我真的很想帮忙,但现在我不确定什么是正确的映射,什么是模糊的部分。因为最新的映射是奇怪的“账号”是您的
TrackingRecords
集合的关键列,但这不是映射id列名。摘要:您的查询通常在所有场景中都会工作。我已经测试过了。如果链映射正确,查询将工作。除非我使用真正的代码,否则我可以像现在一样猜测。抱歉,我想提供帮助,但这样我就可以了这也是不可能的,我感谢你的帮助。我粘贴了准确的代码,并用“foobar”替换了商标字符串。@MrTibs:大多数DBMS将子选择转换为半连接,这些可以通过嵌套查询在内部完成(也和普通的内部连接一样),或其他算法,具体取决于优化器的选择。如果每个TrackingNo正好有一个帐户和一个主帐户,这很有可能,而且一点也不坏。优点是:您不选择子帐户,并且如果不同的连接路径导致它,您将不会获得多个相等的主帐户。我使用它来处理分离的查询,但我讨厌它的外观代码。我认为ORM的目的是简化事情,而不是让事情变得更难。不是我公司的每个人都是NHibernate专家。如果我留下代码,他们不会知道我在做什么。我最终编写了原始SQL。无论如何,谢谢。
var trackRecAccountIdsSubq = DetachedCriteria.For(typeof(TrackingRecord))
                .SetProjection(Projections.Property("AccountId"))
                .Add(
                    Restrictions.Eq("TrackingNo", "123456")); 

var accountMasterIdsSubq = DetachedCriteria.For(typeof(Account))
                .SetProjection(Projections.Property("MasterId"))
                .Add(
                    Subqueries.PropertyIn("AccountId", trackRecAccountIds)); 

var mastersByTrackRecNoCriteria = session.CreateCriteria<Master>()
                .Add(
                    Subqueries.PropertyIn("MasterId", accountMasterIdsSubq);

var mastersByTrackRecNo = mastersByTrackRecNoCriteria.List<Master>();
Select * from t_master where master_id in (
    select master_id from t_account where account_id in (
        select account_id from t_tracking where tracking_no=123456
    )
)