1

次の(簡略化された)エンティティの階層があります。

RootClass
->DescriptorClass
->SomeChild->DescriptorClass
           ->SomeGrandChild

可能であれば、1 回のクエリですべてを取得したいと考えています。

現在、私は以下を持っています:

Session.Query<RootClass>().Where(/*some expressions here*/)
                    .Fetch(v => v.DescriptorClass)
                    .Fetch(v => v.SomeChild).ThenFetch(v => v.SomeGrandChild)
                    .Fetch(v => v.SomeChild).ThenFetch(v => v.DescriptorClass);

正常に動作しますが、SomeChild で 2 つの結合を持つ SQL クエリが作成されます。明らかに、その 2 番目の Fetch(v => v.SomeChild) を取り除く必要がありますが、その方法が見つかりません。私は試した:

Session.Query<RootClass>().Where(/*some expressions here*/)
                    .Fetch(v => v.DescriptorClass)
                    .Fetch(v => v.SomeChild).ThenFetch(v => v.SomeGrandChild)
                    .ThenFetch(v => v.DescriptorClass); //<- wrong, tries to find DescriptorClass on SomeGranchild

Session.Query<RootClass>().Where(/*some expressions here*/)
                    .Fetch(v => v.DescriptorClass)
                    .Fetch(v => v.SomeChild).ThenFetch(v => v.SomeGrandChild)
                    .Fetch(v => v.DescriptorClass); //<- wrong, loads the same DescriptorClass of RootClass, not on SomeChild

NHibernate に SomeChild で単一の結合を作成し、SomeChild の SomeGrandChild と DescriptorClass をフェッチするように指示するにはどうすればよいですか?

4

1 に答える 1

1

このタイプのクエリでは、ラムダの代わりに LINQ クエリ構文を使用するように切り替えてください。これにより、制御が強化され、通常はより効率的でクリーンな SQL が出力されます。

以下のサンプルを見て、エイリアス「c」を使用して Customer エンティティを複数回参照できる方法に注目してください。

var customers =
    (
        from c in session.Query<Customer>()
        from a in c.Addresses
        from pn in c.PhoneNumbers
        where c.Status == "Active"
                && a.City == "Dallas"
                && pn.AreaCode == "972"
        select c )
        .ToList();

これにより、NHibernate を使用した次の SQL が生成されます。

SELECT
    customer0_.CustomerId as Customer1_135_0_,
    customer0_.Status as Customer1_135_1_
FROM
    Customer customer0_
INNER JOIN
    CustomerAddresses customeraddr1_
        ON customer0_.CustomerId=customeraddr1_.CustomerId
INNER JOIN
    CustomerPhoneNumbers customerphon2_
        ON customer0_.CustomerId=customerphon2_.CustomerId
WHERE
    customer0_.Status='Active' /* @p0 */
    AND customeraddr1_.City = 'Dallas' /* @p1 */
    AND customerphon2_.AreaCode = '972' /* @p2 */;
于 2012-10-30T05:11:22.920 に答える