nhibernate的定制<;设置>;质疑

nhibernate的定制<;设置>;质疑,nhibernate,mapping,set,one-to-many,outer-join,Nhibernate,Mapping,Set,One To Many,Outer Join,我想对ClassA.ClassBCollection属性进行筛选和分页。我需要动态更改过滤 默认查询将产生如下结果: select * from ClassA left outer join ClassB on id == FK_ClassB 我可以定制nhibernate集合的查询吗 映射: <class name="ClassA"> <property name="Name" /> &l

我想对
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>

如果我理解你的问题

我可以定制nhibernate集合的查询吗

…正确地说,答案是否定的

我的意思是,如果您考虑获取
ClassA
的实例,并对其
集合进行分页和过滤。那将永远在记忆中完成。(我在末尾附加了映射的功能)

我们可以改变方法 在这种情况下,当您需要一个过滤器并对集合项进行分页时,我强烈建议您换一种方式。创建
标准
QueryOver
HQL
)不是在
ClassA
上,而是在
ClassB

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

<class name="ClassB">
  <property name="Something" />
  <many-to-one name="ClassA" column="FK_ClassB" fetch="join" />
</class>
因为我们使用了ClassA
fetch=“join”
的映射,所以生成的SQL语句将非常类似于这个问题中的第一个片段

因此,通过这种方式,我们可以实现所需的SQL选择,但不能直接使用
ClassA.ClassBCollection
。我们是这样做的

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

当作为
ClassA
的属性加载
ClassBCollection
时,Where子句将始终进行计算。它可能类似于
where=“IsActive=true”

如果ClassA在ClassBCollection中有很多项目,我们可以管理如何借出它们。非常有效的方法是属性批量大小

我可以定制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; }
    }
}
[TestFixture]
公共类StackOverflowQuestion13496270Tests
{
公开辩论会;
[设置]
公共作废设置()
{
session=//获取当前的NHibernate会话
}
[测试]
公共无效查询_ClassA()
{
var results=session.Query()
.Where(x=>x.ClassBCollection.Any(y=>y.Name==“Bob”))
.Fetch(x=>x.ClassBCollection)
.Skip(0)
.Take(50)
.ToList();
}
[测试]
公共无效查询_ClassB()
{
var results=session.Query()
.Where(x=>x.Name==“Bob”)
.Fetch(x=>x.ClassAParent)
.Skip(0)
.Take(50)
.ToList();
}
甲级公共课
{
公共虚拟整数Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟IList类集合{get;set;}
}
公共B类
{
公共虚拟整数Id{get;set;}
公共虚拟字符串名称{get;set;}
//添加此项和适当的映射修改,以便能够导航回父项
公共虚拟ClassA ClassAParent{get;set;}
}
}

这就像是一种折衷:使用ClassA.ClassBCollection或自定义查询,并与ClassA结果集合分离?明白了。我想我的处境和你一样。大集合,这不是延迟加载的最佳选择。所以,当我有ClassA时,我异步地去获取它集合的一部分。。。
[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; }
    }
}