Механизм критериев NHibernate с внутренним соединением и подзапросом

#c# #nhibernate #criteria

#c# #nhibernate #критерии

Вопрос:

Возможно ли в NHibernate создать запрос, который выглядит следующим образом?

 select hi.ContactId
From dbo.vw_HostInterests hi INNER JOIN
    (  Select cm1.ContactId
        From dbo.vw_ContactMoments cm1 INNER JOIN
            (
                Select Contactid
                From dbo.vw_ProfileNaw
                where GenderId = 1000
            ) as pn1 on cm1.ContactId = pn1.ContactId
        where cm1.ActivityId = 1001
    )as cm on hi.ContactId = cm.ContactId
 

где hi.ActivityId = 1038

Мне удалось создать правильный вывод с помощью инструкции IN, но мне бы очень хотелось, чтобы SQL выглядел так. Приведенные ниже критерии показывают часть приведенного выше запроса с инструкцией IN, которую я использовал (но хочу заменить):

 ICriteria criteria = DbSession.CreateCriteria<Contact>();

var dCriteria1 = DetachedCriteria.For(typeof(VwHostInterest))
    .Add(Expression.Eq("ActivityId", 1038))
    .SetProjection(Projections.ProjectionList()
    .Add(Projections.GroupProperty("ContactId")));

var dCriteria2 = DetachedCriteria.For(typeof(VwContactMoment))
    .Add(Expression.Eq("ActivityId", 1001))
    .SetProjection(Projections.ProjectionList()
    .Add(Projections.GroupProperty("ContactId")));

criteria.Add(Subqueries.PropertyIn("ContactId", dCriteria1));
criteria.Add(Subqueries.PropertyIn("ContactId", dCriteria2));

int count = (Int32)criteria
    .SetProjection(Projections.Count("ContactId"))
    .UniqueResult();
 

Ответ №1:

Вероятно, это не тот ответ, который вы ищете, и прошу прощения, если это не так, но мой опыт показывает, что лучшим выбором для таких сложных запросов было бы:

а) Сделайте все это как представление и сопоставьте его в NHibernate

б) Создайте внутренний выбор в виде представления и создайте сопоставление таким образом, чтобы вы могли связать его в своем запросе

b) Или переопределите nhibernate (переопределите как в skip, а не в терминах OO;) и запишите это как именованный запрос, используя собственный SQL.

Ответ №2:

Дает ли этот вложенный запрос тот же результат, что и следующий?

 SELECT hi.ContactId
FROM dbo.vw_HostInterests hi 
INNER JOIN vw_ContactMoments cm1 on hi.ContactId = cm1.ContactId
    AND cm1.ActivityId = 1001
INNER JOIN dbo.vw_ProfileNaw pn1 on pn1.ContactId = cm1.ContactId
    AND pn1.GenderId = 1000   
WHERE hi.ActivityId = 1038