борется с левым соединением в запросе nHibernate - PullRequest
0 голосов
/ 29 ноября 2011

Я изо всех сил пытаюсь реплицировать простое соединение sql left в запросе nHibernate.Другие ответы на SO привели меня в замешательство в отношении того, как лучше всего обрабатывать левые объединения в запросе домена.

Пример:

2 Таблицы БД:

Customer
CustId  INT PK

Orders
OrderId INT PK
CustId  INT FK
Status  INT

1 SQL-запрос:

Select c.CustId from Customer c
left join Orders o on o.CustId = c.CustId and o.Status = 2
where o.OrderId is null

Это позволит получить уникальный список клиентов, у которых нет заказа в статусе 2. Обратите внимание, что в него также входят клиенты, у которых нет заказа навсе.Это надуманный пример для упрощения этого вопроса, но этот тип запроса очень полезен и его нелегко сделать любым другим способом.

Представьте nh сопоставления для "Customer" и "Orders", которые просто отражают таблицы примероввыше.

Существует ли простой способ извлечения моего списка уникальных клиентов, не имеющих статуса 2, в nHibernate, в запросе, без обращения к SQL-запросу или в конечном итоге в сценарии выбора n + 1?

Параметры запроса:

1 linq-to-nhibernate
2 QueryOver
3 HQL
4 Критерии.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 29 ноября 2011

См. http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/queryhql.html#queryhql-joins. Это ссылка Hibernate, а не ссылка nHibernate, но я бы предположил, что они работают одинаково (кстати, этот пост , кажется, подтверждает это):

Вы можете предоставить дополнительные условия соединения, используя HQL с ключевым словом.

от Cat как cat left join cat.kittens как kitten с kitten.bodyWeight> 10.0

Итак, в вашем случае это должно выглядеть как

select c.CustId from Customer c
left join Orders o with o.Status = 2
1 голос
/ 30 ноября 2011

В NHibernate 3.0 есть метод перегрузки для ICriteria .CreateAlias, который принимает 4 параметра, последний параметр - withClause.

Вот пример:

 DetachedCriteria criteria = DetachedCriteria.For<Models.BO.Customer>("customer")
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks),
                "activeTasks", JoinType.LeftOuterJoin, Restrictions.IsNotNull("activeTasks.LockedBy")
            )
            .CreateAlias(ReflectionHelper.PropertyName<Models.BO.Customer>(x => ((Models.BO.Interfaces.ICustomerQueryOnly) x).Tasks2),
                "availableTasks", JoinType.LeftOuterJoin,
                availableTasksRestraction
            )
            .Add(Restrictions.Eq("CustomerBase", _customerBase))
            .Add(Restrictions.Eq("IsActive", true));

который в конечном итоге что-то вроде:

     FROM Customers c
         left join Tasks t on t.customerId = c.Id and (t.DeletedDate is null and 
t.lockedById is null and [etc])
         left join Tasks activetasks [etc]
     where [...]

В этом примере мне нужно извлечь всех клиентов и количество доступных задач и количество активных задач для каждого клиента.

0 голосов
/ 29 ноября 2011

Если сущности не связаны, и вы не хотите отображать отношения, вы можете использовать тэта-соединение.См. здесь

Может быть что-то вроде

Select c from Customer c, Order o 
where o.CustId = c.CustId and o.Status = 2
...