我正在尝试使用DetachedCriteria进行选择,我想在运行时添加OR分隔的几个条件。
如果我使用:
Restrictions.Or( cond1, Restrictions.Or(cond2, Restrictions.Or(cond3, cond4)) )
我得到了我想要的结果。
但如果我像这样使用Disjunction:
var disjunction = Restrictions.Disjunction();
disjunction.Add(cond1);
disjunction.Add(cond2);
disjunction.Add(cond3);
disjunction.Add(cond4);
我有cond1和cond2的实体对他们来说是真实的,在结果我得到它们两次(在列表结果中相同的实体被返回两次)。
我不想使用QueryOver,因为我正在尝试完成一些难以使用QueryOver的东西(我正在尝试做的最终结果是从json的过滤器获取sql查询)。
什么导致分离返回双打?有没有办法在最后添加DISTINCT?我做错了,我不应该在同一张桌子上使用disjunction来处理不同的条件吗?
更新
对于DISTINCT部分:
criteria.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());
或
Projections.Distinct(Projections.Id())
真正的解决方案如RadimKöhler所述 - 正确使用子查询。
答案 0 :(得分:3)
一个小借口:问题没有提供任何映射,也缺少查询...所以人们只能猜出是什么问题。但是,让我们尝试提供一些解释
我们有两个表(如问题下面的一条评论中所示)
父:
ParentId | Name
1 | Parent_A
2 | Parent_B
子:
ChildId | Color | ParentId
1 | green | 1
2 | grey | 1
3 | gold | 1
4 | green | 2
如果我们将在纯SQL
中创建简单选择,请执行此操作SELECT p.ParentId, p.Name
FROM Parent AS p
INNER JOIN Child AS c
ON p.ParentId = c.ParentId
WHERE
c.Color = 'green' OR c.Color = 'grey' OR c.Color = 'gold'
此查询的结果是什么?
1 | Parent_A
1 | Parent_A
1 | Parent_A
2 | Parent_B
如果我们将其转换为类似标准:
var sesion = ... // get session
var parent = sesion.CreateCriteria<Parent>();
var children = parent.CreateCriteria("Children");
// restrict the children
children.Add(Restrictions.Disjunction()
.Add(Restrictions.Eq("Color", "green"))
.Add(Restrictions.Eq("Color", "grey"))
.Add(Restrictions.Eq("Color", "gold"))
);
var list = parent
.SetMaxResults(10) // does not matter in our example, but ... it should be used always
.List<Parent>();
这是Criteria C#代码,它将导致多个Parents (因为事实上,将生成如上所述的相同SQL)
正如我们所看到的,NHiberante方面的问题肯定是不。真! NHibernate不仅是无辜的,而且还在做所需的事情。
解决方案在子选择
中在SQL中它将是这样的
SELECT p.ParentId, p.Name
FROM Parent AS p
WHERE p.ParentId IN (
SELECT c.ParentId
FROM Child AS c
WHERE c.ParentId = p.ParentId
AND c.Color = 'green' OR c.Color = 'grey' OR c.Color = 'gold'
)
这将为我们提供我们最想要的结果:
1 | Parent_A
2 | Parent_B
如何在NHibernate中做到这一点?
var sesion = ... // get session
var parent = sesion.CreateCriteria<Parent>();
//var children = parent.CreateCriteria("Children");
var children = DetachedCriteria.For(typeof(Child));
// restrict the children
children.Add(Restrictions.Disjunction()
.Add(Restrictions.Eq("Color", "green"))
.Add(Restrictions.Eq("Color", "grey"))
.Add(Restrictions.Eq("Color", "gold"))
);
// ad SELECT into this sub-select
children.SetProjection( Projections.Property("ParentId"));
// filter the parent
parent
.Add(Subqueries.PropertyIn("ParentId", children));
var list = parent
.SetMaxResults(10) // does not matter in our example, but ... it should be used always
.List<Parent>();
现在,我们确实有子选择(DetachedCriteria
和Subqueries
NHibernate功能)而且没有更多的重复!