NHibernate:如何在Criteria中检索“拥有”具有特定谓词的所有实体的实体

时间:2009-12-07 17:32:08

标签: nhibernate criteria

我有一套带有一组类别的文章。 如何使用条件界面查询包含具有特定Id的所有类别的所有文章?

这不是“in”,我只需要那些所有必要类别的人 - 以及其他人。部分匹配不应该在那里。

目前我的代码在这种绝望的尝试中失败了:

var c = session.CreateCriteria<Article>("a");
if (categoryKeys.HasItems())
{
    c.CreateAlias("a.Categories", "c");
    foreach (var key in categoryKeys)
        c.Add(Restrictions.Eq("c", key)); //bogus, I know!
}

3 个答案:

答案 0 :(得分:1)

使用“IN”限制,但补充以确保类别匹配的数量等于您要查找的所有类别的数量,以确保所有类别匹配而不只是一个子集。

有关我的意思的示例,您可能需要查看this page,尤其是“Toxi解决方案”标题下的“交叉点”查询。将“书签”替换为“文章”,将“标签”替换为“类别”,以将其映射回您的特定问题。这是他们在那里展示的SQL:

SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
HAVING COUNT( b.id )=3

我相信您也可以使用可能更容易使用Criteria API表示的子查询来表示这一点

SELECT Article.Id
FROM Article 
INNER JOIN (
      SELECT ArticleId, count(*) AS MatchingCategories 
      FROM ArticleCategoryMap  
      WHERE CategoryId IN (<list of category ids>)
      GROUP BY ArticleId
) subquery ON subquery.ArticleId = EntityTable.Id 
WHERE subquery.MatchingCategories = <number of category ids in list>

答案 1 :(得分:0)

我不是百分百肯定,但我认为query by example可能就是你想要的。

答案 2 :(得分:0)

假设Article to Category是一对多关系,而且Category有一个多对一的属性叫做Article,这是一种非常肮脏的方式(我真的不为此感到骄傲,但它有效)

List<long> catkeys = new List<long>() { 4, 5, 6, 7 };

if (catkeys.Count == 0)
    return;

var cr = Session.CreateCriteria<Article>("article")
  .CreateCriteria("Categories", "cat0")
  .Add(Restrictions.Eq("cat0.Id", catkeys[0]));

 if (catkeys.Count > 1)
 {
  for (int i = 1; i < catkeys.Count; i++)
  {
   cr = cr.CreateCriteria("Article", "a" + i)
          .CreateCriteria("Categories", "cat" + i)
          .Add(Restrictions.Eq("cat" + i + ".Id", catkeys[i]));
  }
 }

var results = cr.List<Article>();

它的作用是一遍又一遍地重新加入这种关系,保证你在类别ID之间获得AND。它应该是非常慢的查询,特别是如果ID列表变大。

我提供的解决方案不是推荐的方式,但至少你可以在寻找合适的方式时有所作为。