1

我有以下(简化的)实体层次结构:

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

如果可能的话,我想在一个查询中获取所有内容。

目前我有以下内容:

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 上创建了一个带有两个连接的 SQL 查询。显然,我必须摆脱第二个 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 上创建单个连接,然后获取 SomeGrandChild 和 SomeChild 的 DescriptorClass?

4

1 回答 1

1

对于这种类型的查询,请切换到使用 LINQ 查询语法而不是 lambda,因为它可以为您提供更多控制权,并且通常会输出更高效、更清晰的 SQL。

查看下面的示例,并注意我如何能够通过使用别名“c”多次引用客户实体。

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 回答