2010-12-10 59 views
1

我有一个问题列表,每个问题链接到一个标签列表。NHibernate的多对多标准

,后面的数据:

Question1 : Tag1 
Question2 : Tag1, Tag2 
Question3 : Tag1, Tag2, Tag3 
Question4 : Tag1, Tag3 

以下标准:

var tagsIds = new int[] { tag1, tag2 }; 

var res = session.CreateCriteria<Question>() 
    .CreateCriteria("Tags") 
    .Add(Restrictions.In("id", tagsIds)) 
    .List<Question>(); 

回报(我明白为什么,在 “中” 像一个或行为)

Question1, Question2, Question3, Question4 

或者我只想得到

Question2, Question3 

因为它们都有tag1和tag2。 我有办法做到这一点吗?

在SQL中,我会做这样的事情:

SELECT * 
FROM Question q 
WHERE EXISTS (
    SELECT * 
    FROM QuestionsToTags qtt 
    WHERE qtt.Question_id = q.Id 
    AND qtt.Tag_id IN (1, 2) 
    GROUP BY qtt.Question_id 
    HAVING COUNT(qtt.Question_id) >= 2 
) 

回答

0

用HQL:

var q = NHibernateSession.CreateQuery(
@"from Question question 
    where exists( 
     select q.id from Question q 
     join q.Tags t 
     where 
      t.id in (:ids) 
      and q.id = question.id 
     group by q.id 
     having count(t.id)=:c_count)"); 

q.SetParameterList("ids", tagIds); 
q.SetInt32("c_count", tagIds.Length); 

并使用的ICriteria:

// here is the exists part 
var dCriteria = DetachedCriteria.For<Question>("q") 
    .SetProjection(Projections.GroupProperty(Projections.Id())) 
    .Add(Restrictions.Eq(Projections.Count(Projections.Id()), tagIds.Length)) 
    // here we filter on the "parent" criteria 
    .Add(Restrictions.EqProperty("q.id", "question.Id")) 
    .CreateCriteria("Tags") 
    .Add(Restrictions.In("id", tagIds)); 

var crit = NHibernateSession 
    .CreateCriteria<Question>("question") 
    .Add(Subqueries.Exists(dCriteria)); 
1

如果你只有两个,然后使用和制约

var res = session.CreateCriteria<Question>() 
    .CreateCriteria("Tags") 
    .Add(Restrictions.And(Restrictions.Eq("id", tag1), Restrictions.Eq("id", tag2)) 
    .List<Question>(); 

如果你有两个以上或有未知数量的使用连词:

var conj = new Conjunction(); 
// use a loop to add all tags if number is unknown 
conj.Add(Restrictions.Eq("id", tag1); 
conj.Add(Restrictions.Eq("id", tag2); 

var res = session.CreateCriteria<Question>() 
    .CreateCriteria("Tags") 
    .Add(conj) 
    .List<Question>(); 

还有一个Disjunction类来处理多个或条件。

+0

谢谢你,但是这是行不通的,因为它会产生下面的SQL:选择[剪断] FROM “问题” this_ inner join QuestionsToTags tags3_ on this_.Id = tags3_.Question_id内连接“标签”tag1_在tags3_.Tag_id = tag1_.Id WHERE(tag1_.Id = 1和tag1_.Id = 2)。所以没有返回,因为ID不能是1和2 – mathieu 2010-12-11 19:05:21