NHibernate - присоединение к подзапросу с использованием ICriteria - PullRequest
2 голосов
/ 13 мая 2009

У меня есть SQL-запрос, который мне нужно представить с помощью API-интерфейса NHibernate.

   SELECT u.Id as Id, 
    u.Login as Login, 
    u.FirstName as FirstName, 
    u.LastName as LastName, 
    gm.UserGroupId_FK as UserGroupId,
    inner.Data1,
    inner.Data2,
    inner.Data3
    FROM dbo.User u inner join 
    dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
    left join
    (
        SELECT
        di.UserAnchorId_FK,
        sum(di.Data1) as Data1, 
        sum(di.Data2) as Data2, 
        sum(di.Data3) as Data3
        FROM
        dbo.DailyInfo di 
        WHERE di.Date between '2009-04-01' and '2009-06-01' 
        GROUP BY di.UserAnchorId_FK
    ) inner ON inner.UserAnchorId_FK = u.Id
    WHERE gm.UserGroupId_FK = 195 

Попытки до сих пор включали отображение классов 'User' и 'DailyInfo' (мои сущности) и превращение объекта DailyInfo в свойство объекта User. Тем не менее, как отобразить отношения между внешними ключами между ними до сих пор остается загадкой, то есть

<one-to-one></one-to-one>

<one-to-many></one-to-many>

<generator class="foreign"><param name="property">Id</param></generator> (!) 

Решения в Интернете обычно связаны с подзапросами в предложении WHERE, однако вместо этого мне нужно оставить соединение в этом подзапросе, чтобы гарантировать, что значения NULL возвращаются для строк, которые не объединяются.

У меня такое ощущение, что я должен использовать критерии для внешнего запроса, а затем формировать 'соединение' с DetachedCriteria для представления подзапроса?

Ответы [ 2 ]

1 голос
/ 05 января 2012

Та же проблема, с которой я столкнулся, и я не получил никаких решений. Так что я взломал перехватчик

Запрос, сгенерированный критериями

SELECT u.Id as Id, 
u.Login as Login, 
u.FirstName as FirstName, 
u.LastName as LastName, 
gm.UserGroupId_FK as UserGroupId,
inner.Data1,
inner.Data2,
inner.Data3
FROM dbo.User u inner join 
dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
InnerJoin inner ON inner.UserAnchorId_FK = u.Id
WHERE gm.UserGroupId_FK = 195

Здесь InnerJoin - фиктивная таблица, которая имеет отношение 1-1 к пользователю. Столбцы в InnerJoin являются возвращаемыми значениями подзапроса внутреннего соединения

Критерии для пользователя и InnerJoin

DetachedCriteria forUser = DetachedCriteria.For<User>();
forUser.CreateCriteria("InnerJoin");

Теперь вы можете сделать перехватчик для редактирования запроса

public interface CustomInterceptor : IInterceptor, EmptyInterceptor
{    
 SqlString IInterceptor.OnPrepareStatement(SqlString sql)
 {
    string query = sql.ToString();
     if (query.Contains("InnerJoin "))
     {
        sql = sql.Replace("InnerJoin ", "(select [vals] form dbo.DailyInfo [where conditions])");
     }
     return sql;
 }
}

Для значений Return из нескольких таблиц, включая объединенный подзапрос, вы можете использовать NHibernate DTO И сессия такова

CustomInterceptor custonInterceptor=new CustomInterceptor(); 

sessionFactory.OpenSession(custonInterceptor);

И последний запрос будет похож на то, что именно вы хотите получить

0 голосов
/ 14 мая 2009

Что касается сопоставления отношений, похоже, что у вас есть отношение один-ко-многим между пользователем и DailyInfo:

<!-- User mapping -->
<bag name="DailyInfos" inverse="true">
    <key column="UserAnchorId_FK" />
    <one-to-many class="Namespace.To.DailyInfo, Namespace" />
</bag>

<!-- DailyInfo mapping -->
<many-to-one name="User" column="UserAnchorId_FK" />

Что касается остальных, я не совсем уверен в данный момент ... похоже, у вас может быть много ко многим между User и Group через таблицу GroupMember, которая осложняющий фактор. Помните, что вы можете выполнить .CreateCriteria("Association path", jointype) для критериев, чтобы создать подкритерии с указанным типом соединения. Может помочь публикация краткого изложения ваших отношений класса / таблицы.

...