与IQueryOver连接的Nhibernate条件
我在google和stackoverflow上搜索了差不多2个小时,但没有找到任何解决方案 我有两个表,一对多与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
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>();