2010-12-10 93 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