NHibernate: как получить сущность, которая «имеет» все сущности с определенным предикатом в критериях - PullRequest
1 голос
/ 07 декабря 2009

У меня есть статья с набором категорий. Как я могу запросить, используя интерфейс критериев, для всех статей, которые содержат все категории с определенным идентификатором?

Это не "в", мне нужны исключительно те, у кого есть все необходимые категории - и другие. Частичные совпадения не должны быть там.

В настоящее время мой код терпит неудачу с этой отчаянной попыткой:

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 ]

1 голос
/ 08 декабря 2009

Используйте ограничение "IN", но добавьте его, чтобы убедиться, что количество совпадений категорий равно количеству всех категорий, которые вы ищете, чтобы убедиться, что все категории соответствуют и не просто подмножество.

В качестве примера того, что я имею в виду, вы можете взглянуть на эту страницу , особенно на запрос "Пересечение" под заголовком "Решение 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

Полагаю, вы также можете представить это с помощью подзапроса, который проще представить с помощью API Criteria

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>
0 голосов
/ 08 декабря 2009

Предположение, что Article to 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>();

То, что он делает, это снова и снова присоединяет отношения, гарантируя вам И между категориями идентификаторов. Это должен быть очень медленный запрос, особенно если список идентификаторов становится большим.

Я предлагаю это решение как НЕ рекомендуемый способ, но, по крайней мере, у вас может быть что-то работающее при поиске подходящего.

0 голосов
/ 07 декабря 2009

Я не уверен на 100%, но я думаю, запрос на примере может быть тем, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...