NHibernate beaucoup à de nombreux critères
-
08-10-2019 - |
Question
J'ai une liste de questions, chacune liée à une liste de balise.
Et les données suivantes:
Question1 : Tag1
Question2 : Tag1, Tag2
Question3 : Tag1, Tag2, Tag3
Question4 : Tag1, Tag3
Les critères suivants:
var tagsIds = new int[] { tag1, tag2 };
var res = session.CreateCriteria<Question>()
.CreateCriteria( "Tags" )
.Add( Restrictions.In( "id", tagsIds ) )
.List<Question>();
renvoie (je comprends pourquoi, le "in" agit comme un OR)
Question1, Question2, Question3, Question4
Ou je voudrais obtenir seulement
Question2, Question3
comme ils ont tous deux balise1 ET tag2. J'y suis une façon de le faire?
Dans SQL, je ferais quelque chose comme:
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
)
La solution 2
Utilisation 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);
Et en utilisant un 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));
Autres conseils
Si vous avez seulement deux puis utilisez une restriction et
var res = session.CreateCriteria<Question>()
.CreateCriteria( "Tags" )
.Add( Restrictions.And(Restrictions.Eq("id", tag1), Restrictions.Eq("id", tag2))
.List<Question>();
Si vous avez plus de deux ou un nombre inconnu puis utilisez Conjonction:
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>();
Il y a aussi une classe Disjunction à poignée multiples ou conditions.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow