我有一套带有一组类别的文章。 如何使用条件界面查询包含具有特定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!
}
答案 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列表变大。
我提供的解决方案不是推荐的方式,但至少你可以在寻找合适的方式时有所作为。