nHibernate QueryOver:过滤主元素长度和子元素长度

Posted

技术标签:

【中文标题】nHibernate QueryOver:过滤主元素长度和子元素长度【英文标题】:nHibernate QueryOver: Filter length of main element and the length of sub elements 【发布时间】:2020-12-08 10:06:41 【问题描述】:

我有两个实体:PakagePolePakage 包含多个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 &gt;= 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 QueryOver 两次加入一个集合

NHibernate 3.0:没有使用QueryOver的FirstOrDefault()?

NHibernate 使用 QueryOver 和 Future 加入两个集合

使用 NHibernate 3.0 QueryOver 或 LINQ 提供程序的权衡

NHibernate 使用带有 WHERE IN 的 QueryOver