在NHibernate中,使用Disjunction会得到双重结果
本文关键字:结果 Disjunction NHibernate 使用 | 更新日期: 2023-09-27 18:14:17
我试图用DetachedCriteria进行选择,我想在运行时添加几个由OR分隔的条件。
如果我使用:
Restrictions.Or( cond1, Restrictions.Or(cond2, Restrictions.Or(cond3, cond4)) )
我得到我想要的结果。
但是如果我像这样使用析取:
var disjunction = Restrictions.Disjunction();
disjunction.Add(cond1);
disjunction.Add(cond2);
disjunction.Add(cond3);
disjunction.Add(cond4);
并且我有cond1和cond2为真的实体,在结果中我得到它们两次(相同的实体在列表结果中返回两次)。
我不希望使用QueryOver,因为我正试图完成一些很难用QueryOver做的事情(我试图做的最终结果是从json的过滤器中获得sql查询)。
是什么导致析取返回双精度?有没有办法在结尾添加一个DISTINCT ?我做错了吗,我不应该在同一个表的不同条件下使用析取法吗?
更新:
对于DISTINCT部分:criteria.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());
或
Projections.Distinct(Projections.Id())
真正的解决方案如Radim Köhler所述-正确使用子查询
一个小借口:这个问题没有提供任何映射,也缺少查询…所以我们只能猜测问题出在哪里。但是让我们试着提供一些解释
为什么接收不明显?
让我们有两个表(如问题下面的一个评论所示)
父: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>();
这是标准c#代码,这将导致多个父(因为事实,相同的SQL将生成如上所述)
正如我们所看到的,问题肯定是在nhibernate端而不是。真的!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特性),没有更多的重复!