与IQueryOver连接的Nhibernate条件

与IQueryOver连接的Nhibernate条件,nhibernate,subquery,criteria,queryover,icriteria,Nhibernate,Subquery,Criteria,Queryover,Icriteria,我在google和stackoverflow上搜索了差不多2个小时,但没有找到任何解决方案 我有两个表,一对多 1) [Accounts] PK Account_Id int User_ID 2) [Temporary_Accounts] Fk Account_Id char IsAccepted {'1','0',null} varchar name 和2个映射类 1) Acc int Id; User user; TempAcc Temp; //cause each Account

我在google和stackoverflow上搜索了差不多2个小时,但没有找到任何解决方案

我有两个表,一对多

1) [Accounts]
PK Account_Id
int User_ID


2) [Temporary_Accounts]
Fk Account_Id
char IsAccepted   {'1','0',null}
varchar name
和2个映射类

1) Acc
int Id;
User user;
TempAcc Temp; //cause each Account can have 0 or one TempAcc (with IsAccepted == null)

2)TempAcc
int Id;
bool IsAccepted;
string name;
我想显示给定用户id的所有帐户,以及在[Temporary_accounts]中有记录且IsAccepted==null的帐户的附加信息(f.e name)

因此,SQL应该如下所示:

select acc.Account_Id, acc.User_Id, tempacc.Name 

from Account acc left join Temporary_Account tempacc 
on (acc.Account_ID = tempacc.Account_Id and tempacc.IsAccepted is null)
where (acc.User_Id = 65);
但我的问题是:

IQueryOver<Acc> query = (...)
query.JoinAlias(f => f.Temp,
                () => Temp,
                JoinType.LeftOuterJoin)
     .Where(f => f.Temp.IsAccepted == null)
     .And(f => f.user.id == userid);
所以我得到的结果比第一次正确查询的结果要少

您知道我应该更改什么,或者我可以做什么来获得第一次查询的结果吗?我的想法是将Accounts表与子查询leftjoin,该子查询从Temporary_Accounts表中选择所有IsAccepted=null帐户,但我不确定如何在Iqueryover或Icriteria中执行此操作


如果您有任何建议,我将不胜感激。

,因为您的示例sql将生成笛卡尔乘积,介于
Acc
Temp
之间

您需要的查询将使用子查询,如下所示:

Acc accountAlias = null;
var subQuery = QueryOver.Of<Temp>()
               .Where(x=>x.IsAccepted==null)
               .And(x=>x.Account.Id==accountAlias.Id);

var results = session.QueryOver<Acc>(()=>accountAlias)
              .Where(x=>x.User.Id==65)
              .WithSubquery.WhereExists(subQuery);
关于的这篇文章对于使用QueryOver解决复杂查询非常有帮助

更新:

如果您还需要查找
临时账户中没有任何对应行的
账户
,则需要两个

Acc accountAlias=null;
var hasTempAccount=QueryOver.Of()
。其中(x=>x.IsAccepted==null)
和(x=>x.Account.Id==accountAlias.Id);
var doesNotHaveTempAccount=QueryOver.Of()的
和(x=>x.Account.Id==accountAlias.Id);
var results=session.QueryOver

Temp tempAlias=null;
accountAlias=null;
dto-dto=null;
var results=Session.QueryOver(()=>accountAlias)
.JoinAlias(x=>x.TempAccounts,()=>tempAlias,JoinType.LeftOuterJoin,
Restrictions.IsNull(Projections.Property(()=>tempAlias.IsAccepted))
)
.其中(x=>x.Account.Id==65)
.SelectList(list=>list
。选择(()=>accountAlias.Id)。使用别名(()=>dto.AccountId)
。选择(()=>accountAlias.User.Id)。使用别名(()=>dto.UserId)
。选择(()=>tempalica.Name)。使用别名(()=>dto.TempAccName)
)
.SetResultTransformer(Transformers.AliasToBean())
.List();

因为在
Acc
Temp
之间有一个1-Many,所以示例sql将生成笛卡尔乘积

您需要的查询将使用子查询,如下所示:

Acc accountAlias = null;
var subQuery = QueryOver.Of<Temp>()
               .Where(x=>x.IsAccepted==null)
               .And(x=>x.Account.Id==accountAlias.Id);

var results = session.QueryOver<Acc>(()=>accountAlias)
              .Where(x=>x.User.Id==65)
              .WithSubquery.WhereExists(subQuery);
关于的这篇文章对于使用QueryOver解决复杂查询非常有帮助

更新:

如果您还需要查找
临时账户中没有任何对应行的
账户
,则需要两个

Acc accountAlias=null;
var hasTempAccount=QueryOver.Of()
。其中(x=>x.IsAccepted==null)
和(x=>x.Account.Id==accountAlias.Id);
var doesNotHaveTempAccount=QueryOver.Of()的
和(x=>x.Account.Id==accountAlias.Id);
var results=session.QueryOver

Temp tempAlias=null;
accountAlias=null;
dto-dto=null;
var results=Session.QueryOver(()=>accountAlias)
.JoinAlias(x=>x.TempAccounts,()=>tempAlias,JoinType.LeftOuterJoin,
Restrictions.IsNull(Projections.Property(()=>tempAlias.IsAccepted))
)
.其中(x=>x.Account.Id==65)
.SelectList(list=>list
。选择(()=>accountAlias.Id)。使用别名(()=>dto.AccountId)
。选择(()=>accountAlias.User.Id)。使用别名(()=>dto.UserId)
。选择(()=>tempalica.Name)。使用别名(()=>dto.TempAccName)
)
.SetResultTransformer(Transformers.AliasToBean())
.List();

谢谢你,马克。我可能错了,但我认为它会创建某种伪内连接,我需要左外连接。它将只返回带有临时帐户的帐户,但不会返回没有临时帐户的帐户(我也需要)。因此,您希望:“在TempAccounts中有IsAccepted为null的条目的帐户列表,以及在TempAccounts表中没有条目的所有帐户”?不幸的是,这并不容易。例如,如果用户_id=56有20个帐户,我希望正好显示20个帐户,但对于临时_帐户表中记录为isacpted=null的这些帐户,我希望获取有关该临时_帐户名的信息。简单左联接+其中不起作用原因1帐户\u Id可能有a)临时表中没有记录或b)1/多个isAccepted='1'的记录c)1/多个isAccepted='0'或d)0/1个isAccepted=null的记录。我问题中的第一个查询确实符合我的要求,但如何将其转换为IqueryOver?Thx用于更新标记,但这不是解决方案。该查询不会返回用户Id为65且IsAccepted='0'的示例帐户。正如我所说,我希望显示这样的帐户,但不显示其他信息(tempacc.Name)。我只需要与临时_Accounts表(IsAccepted=null的Accounts)的一部分进行某种左连接。我试图找到一个解决方案,但QueryOver/ICriteria似乎没有HQL所具有的“WITH”子句的任何等价项,因此不可能添加这样的条件:“on(acc.Account_ID=tempacc.Account_ID和tempacc.IsAccepted为null)”我已经用一个使用QueryOver添加额外连接条件的示例更新了我的答案。谢谢Mark。我可能错了,但我认为它会创建某种伪内连接,我需要左外连接。它将只返回带有临时帐户的帐户,但不会返回没有临时帐户的帐户(我也需要)。因此,您希望:“在TempAccounts中有IsAccepted为null的条目的帐户列表,以及在TempAccounts表中没有条目的所有帐户”?不幸的是,这并不容易。例如,如果用户_id=56有20个帐户,我希望正好显示20个帐户,但对于临时_帐户表中记录为isacpted=null的这些帐户,我希望获取有关该临时_帐户名的信息。简单左连接
select *
from Accounts a
where a.User_Id=65
and exists (
    select t.Account_Id
    from Temporary_Accounts t
    where t.IsAccepted is null and t.Account_Id=a.Account_Id
)
Acc accountAlias = null;
var hasTempAccount = QueryOver.Of<Temp>()
               .Where(x=>x.IsAccepted==null)
               .And(x=>x.Account.Id==accountAlias.Id);

var doesNotHaveTempAccount = QueryOver.Of<Temp>()
               .And(x=>x.Account.Id==accountAlias.Id);

var results = session.QueryOver<Acc>(()=>accountAlias)
  .Where(x=>x.User.Id==65)
  .Where(Restrictions.Disjunction()
    .Add(Subqueries.WhereExists(hasTempAccount))
    .Add(Subqueries.WhereNotExists(doesNotHaveTempAccount))     
  );
Temp tempAlias = null;
Account accountAlias = null;
dto dto = null;
var results = Session.QueryOver<Account>(()=>accountAlias)
  .JoinAlias(x=>x.TempAccounts,()=>tempAlias,JoinType.LeftOuterJoin,
    Restrictions.IsNull(Projections.Property(()=>tempAlias.IsAccepted))
  )
  .Where(x=>x.Account.Id==65)
  .SelectList(list=>list
      .Select(()=>accountAlias.Id).WithAlias(()=>dto.AccountId)
      .Select(()=>accountAlias.User.Id).WithAlias(()=>dto.UserId)
      .Select(()=>tempAlias.Name).WithAlias(()=>dto.TempAccName)
  )
  .SetResultTransformer(Transformers.AliasToBean<dto>())
  .List<dto>();