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セットのクエリをなんとかカスタマイズできますか?

...正解です。答えはNOです。

つまり、インスタンスを取得し、そのコレクションClassAに対してページングとフィルタリングを実行することを考えている場合です。<set>それは常にメモリ内で行われます。(最後に追加したマッピングでできること)

アプローチを変えることができます

この場合、フィルターとコレクションアイテムのページングが必要な場合は、逆の方法を強くお勧めします。CriteriaQueryOverHQL)を作成するのでは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>();

ClassAのマッピングを使用したためfetch="join"、結果のSQLステートメントはこの質問の最初のスニペットと非常によく似ています。

したがって、このようにして、目的のSQL Selectを実現できますが、ClassA.ClassBCollection直接使用することはできません。私たちはこのようにそれをしました...

ノート:

マッピングに影響を与えることができるフィルター/ページング<set>は​​、where句の静的フィルターと値をフェッチするスタイルです。

Where句はClassBCollection、のプロパティとしてロードするときに常に評価されますClassA。それは次のようになる可能性があります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 に答える