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

问题描述

我有两个实体:PakagePolePakage包含多个Poles,它们在打包时都喜欢作为反向集。

我有一个GUI,如果没有在GUI上设置任何限制,它会显示所有Pakages。可能的限制之一是定义Pakage的最小长度。这很棒。但我不应该在Poles显示(并考虑)Pakages的长度。因此,如果用户将最小长度设置为2.0m,则我必须显示所有长度大于等于2.0m的Pakages,以及所有包含长度大于等于2.0的Pakages的{​​{1}} m。

Pole

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

第二种方法不起作用,因为从nHibernate生成sql做了这样的事情:

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

这是错误的,因为WHERE ( this_.length >= @p0 OR this_.length >= @p1); 是包装。因此,这两个限制都在同一字段上起作用,而在pole.length字段上却没有。

this_解决方

解决方法

您需要为联接表创建别名并在限制中使用它。像这样:

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