nHibernate QueryOver:过滤主元素长度和子元素长度
Posted
技术标签:
【中文标题】nHibernate QueryOver:过滤主元素长度和子元素长度【英文标题】:nHibernate QueryOver: Filter length of main element and the length of sub elements 【发布时间】:2020-12-08 10:06:41 【问题描述】:我有两个实体:Pakage
和 Pole
。 Pakage
包含多个Poles
,它们在包中被喜欢作为反向集。
如果没有在 GUI 上设置任何限制,我有一个显示所有 Pakages
的 GUI。可能的限制之一是定义Pakage
的最小长度。这很好用。但是不,我还应该在Pakages
中显示(并考虑)Poles
的长度。因此,如果用户设置的最小长度为 2.0m,我必须显示所有长度 >= 2.0m 的 Pakages
以及包含长度 >= 2.0m 的 Pole
的所有 Pakages
。
public class Pakage : IComparable
public virtual decimal Length get; set;
public virtual ISet<Pole> Poles get; set; = new HashSet<Pole>();
/* other stuff */
public class Pakage : IComparable
public virtual decimal Length get; set;
/* other stuff */
nHibernate 映射在Pakage
<set name="Poles" table="pole" inverse="true">
<key column="pakageid" foreign-key="FK_pole_pakage" />
<one-to-many class="Pole" />
</set>
现在我想查询所有包并在网格视图中列出它们。为了过滤包裹,我有几个数字上下元素。首先我尝试了这个:
var query = session.QueryOver<Pakage>();
if (seLengthFrom.EditValue != null)
query.Where(pakage => pakage.Length >= seLengthFrom.Value || pakage.Poles.Count(p => p.Length >= seLengthFrom.Value) > 0);
这给了我一个错误:'variable 'pakage' of type 'App.Pakage' referenced from scope '', but it is not defined
因此我将其更改为以下内容,这会导致加载时间更长,因为我要加载更多元素:
var query = session.QueryOver<Pakage>();
var poleJoin = query.Left.JoinQueryOver(pakage => pakage.Pole);
if (seLengthFrom.EditValue != null)
query.Where(
Restrictions.Disjunction()
.Add(Restrictions.Where<)Pakage>(x => x.Length >= seLengthFrom.Value))
.Add(Restrictions.Where<Pole>(z => z.Length >= seLengthFrom.Value))
);
IList<Pakage> pakageList = query.TransformUsing(Transformers.DistinctRootEntity).List();
第二种方法不起作用,因为从 nHibernate 生成的 SQL 做了这样的事情:
WHERE (
this_.length >= @p0
OR this_.length >= @p1);
这是错误的,因为this_
将是包装。因此,这两个限制都适用于同一个字段,但不适用于pole.length 字段。
select all Pakages which have a length >= the user input OR which contain a Pole which has a length the user input
有解决办法吗
【问题讨论】:
【参考方案1】:您需要为连接表创建别名并在限制中使用它。像这样的:
Pole poleJoin = null; // <- created alias
session.QueryOver<Pakage>()
.JoinAlias(x => x.Poles, () => poleJoin, JoinType.LeftOuterJoin)
.Where(x => x.Length >= seLengthFrom.Value) || poleJoin.Length >= seLengthFrom.Value))
.Select(Projections.RootEntity())
.TransformUsing(Transformers.DistinctRootEntity)
.List();
【讨论】:
这行得通。谢谢你。我还通过在返回 pakageIds 的子查询中应用过滤来改进加载时间,因此我不需要DistinctRootEntity
转换器并且查询要快得多。
我认为由于 select 语句中存在 Pole 字段,子查询要快得多。也可以通过添加.Select(Projections.RootEntity())
来避免(添加到回答中)以上是关于nHibernate QueryOver:过滤主元素长度和子元素长度的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Nhibernate 中对子集合进行 QueryOver
NHibernate 3.0:没有使用QueryOver的FirstOrDefault()?
NHibernate 使用 QueryOver 和 Future 加入两个集合