1

我想对ClassA.ClassBCollection属性进行过滤和分页。我需要动态更改过滤。

默认查询将产生如下结果:

    select * from ClassA 
             left outer join ClassB 
             on id == FK_ClassB

我可以以某种方式自定义对 nhibernate 集的查询吗?

映射:

<class name="ClassA">
    <property name="Name" />
    <set name="ClassBCollection">
      <key column="FK_ClassB" on-delete="cascade" />
      <one-to-many class="ClassB" />
    </set>
  </class>

  <class name="ClassB">
    <property name="Something"/>
  </class>
4

2 回答 2

0

如果我明白你的问题...

我可以以某种方式自定义对 nhibernate 集的查询吗?

...正确,答案是否定的。

我的意思是,如果您考虑获取实例ClassA并对其<set>集合进行一些分页和过滤。这将始终在内存中完成。(我们可以用我在末尾附加的映射做什么)

我们可以改变方法

在这种情况下,当您需要过滤器并对集合项进行分页时,我强烈建议您采用另一种方式。创建Criteria( QueryOver, HQL) 不是在 上ClassA而是在ClassB.

首先,我们必须扩展ClassB映射:

<class name="ClassB">
  <property name="Something" />
  <many-to-one name="ClassA" column="FK_ClassB" fetch="join" />
</class>

然后创建一个Criteria这样的

var criteria = NHSession.Current.CreateCriteria<ClassB>();

criteria
    .Add(new InExpression("ClassA", new object[] {1})) // id of one or more ClassA
    .AddOrder(new Order("Something", true))            // Order By
    .SetFirstResult(2)                                 // Skip
    .SetMaxResults(10);                                // Take

var list = criteria.List<ClassB>();

因为我们使用了 ClassAfetch="join"的映射,所以生成的 SQL 语句将与此问题中的第一个片段非常相似。

所以这样一来,我们就可以实现想要的SQL Select,但是不能ClassA.ClassBCollection直接使用。我们是这样做的...

笔记:

我们可以影响<set>映射的过滤器/分页是 where 子句中的静态过滤器和获取值的样式。

当加载ClassBCollectionClassA. 它可能就像where="IsActive=true"

如果 ClassA 可以在 ClassBCollection 中有很多项目,我们可以管理它们的加载方式。非常有效的方法是属性批大小记录在这里

于 2012-11-21T18:53:18.820 回答
0

我可以以某种方式自定义对 nhibernate 集的查询吗?

我不完全确定这意味着什么。如果您的意思是,我可以在集合上查询和使用 WHERE 子句吗,答案是肯定的。就是这样:

[TestFixture]
public class StackOverflowQuestion13496270Tests
{
    public ISession session;

    [SetUp]
    public void SetUp()
    {
        session = // Get the current NHibernate session
    }

    [Test]
    public void Query_ClassA()
    {
        var results = session.Query<ClassA>()
            .Where( x => x.ClassBCollection.Any( y => y.Name == "Bob" ) )
            .Fetch( x => x.ClassBCollection )
            .Skip( 0 )
            .Take( 50 )
            .ToList();
    }

    [Test]
    public void Query_ClassB()
    {
        var results = session.Query<ClassB>()
            .Where( x => x.Name == "Bob" )
            .Fetch( x => x.ClassAParent )
            .Skip( 0 )
            .Take( 50 )
            .ToList();
    }

    public class ClassA
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual IList<ClassB> ClassBCollection { get; set; }
    }

    public class ClassB
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }

        // Add this and the appropriate mapping modifications to be able to navigate back to the parent
        public virtual ClassA ClassAParent { get; set; }
    }
}
于 2012-11-21T23:04:01.873 回答