0

我使用嵌套集模型存储类别的层次结构,也就是说,每个类别都有一个Left和一个Right值,每个类别都有一个比任何父项更高Left和更小的值。Right

我想查询属于某个类别(包括该类别)的子类别的所有类别。也就是说,我需要从给定类别开始的整个子树。

如果子树的根 id 由 @catId 给出,我可以使用以下 SQL 来获取子树:

select * 
    from Category c, 
    (select [Left], [Right] from Category where Id = @catId) as t
where c.[Left] >= t.[Left] 
 and c.[Right] <= t.[Right]

现在我正在尝试使用 NHibernate 和 QueryOver API 来做类似的事情。那是我有点卡住的地方。

如果我把它分成两个查询,这很容易:

var cat = session.Get<Category>(catId);

var matches = session.QueryOver<Category>()
                     .Where(x => x.Left >= cat.Left && x.Right <= cat.Right)
                     .List();

但这是两个查询 - 一个会更好。我试图提出一个使用子查询的解决方案,虽然这在技术上可行,但查询可能不是最佳的,因为现在执行了两个子查询而不是一个。

var matches = session.QueryOver<Category>()
                     .WithSubquery.WhereProperty(x => x.Left)
                        .Ge(QueryOver.Of<Category>()
                          .Where(c => c.Id == catId)
                          .Select(c => c.Left))
                      .WithSubquery.WhereProperty(x => x.Right)
                        .Le(QueryOver.Of<Category>()
                           .Where(c => c.Id == catId)
                           .Select(c => c.Right)).List();

(除此之外,并非所有 DBMS 都支持返回标量值的子查询,例如 SqlServerCE,但这是另一个问题)

有没有更好的方法来实现这一目标?如有必要,我可以针对这种情况切换查询 API。因此,如果 eq 在 HQL 中有一种巧妙的方法,我可以接受。

4

1 回答 1

1

我认为获得一个包含嵌套集中树的子树将类似于(SQL):-

SELECT 
    node.*
FROM 
    Category AS node,
    Category AS parent
WHERE 
    node.left BETWEEN parent.left AND parent.right
    AND parent.TreeID = @catID
ORDER BY 
    node.left;

这将使用 QueryOver (AFAIK) 中不可能的 CROSS JOIN

但是,在HQL甚至更好的linq中都是可能的。

于 2013-04-16T09:08:43.773 回答