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

nHibernate QueryOver: Filter length of main element and the length of sub elements

我有两个实体:PakagePolePakage 包含多个 Poles,在 pakage 中喜欢作为反向集。

我有一个 GUI,如果没有对 GUI 设置任何限制,它会显示所有 Pakages。可能的限制之一是定义 Pakage 的最小长度。这很好用。但是不,我还应该在 Pakages 中显示(并考虑)Poles 的长度。因此,如果用户设置的最小长度为 2.0m,我必须显示所有长度 >= 2.0m 的 Pakages 以及包含长度 >= 2.0 的 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 */
}

Pakage

中的 nHibernate 映射
<set name="Poles" table="pole" inverse="true">
  <key column="pakageid" foreign-key="FK_pole_pakage" />
  <one-to-many class="Pole" />
</set>

现在我想查询所有包并在网格视图中列出它们。为了过滤 pakages,我有几个数字 up 和 down 元素。首先我尝试了这个:

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

您需要为加入的 table 创建别名并在限制中使用它。像这样:

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();