2012-01-30 3 views
1
запроса NHibernate

запросе HQL является:Транслейтинг HQL в другой форме

from BusinessObject as businessobject 
    left outer join businessobject.BussinesPartner as businesspartner 
    left outer join businessobject.Document as document 
    left outer join businessobject.Group as group "; 
where businessobject.Date >= :datefrom and businessobject.Date <= :dateto 
    and (:filter = '' 
      or :filter is null 
      or businesspartner.Name like '%' || :filter || '%' 
      or group.Name like '%' || :filter || '%' 
      or document.Name like '%' || :filter || '%') 

Я не хочу использовать HQL. Я также хочу получить строго типизированную коллекцию результатов без использования неудобного и беспорядочного SetResultTransformer. Я бы предпочел использовать Query <>(), но я не знаю, как заставить внешние соединения.

Когда я пишу это в форме запроса <>(), он не вернет результат, для которого дата находится в правильном диапазоне, и filter = "", если, например, BusinessPartner имеет значение NULL. В то время как «где» логическое выражение истинно для этих объектов, похоже, они не в наборе результатов в любом случае из-за использования внутренних соединений:

session.Query<BusinessObject>() 
     .Where(x => 
      (x.Date >= criteria.DateFrom && x.Date <= criteria.DateTo 
      && (criteria.Filter == "" 
      || x.BusinessPartner.Name.Contains(criteria.Filter) 
      || x.Group.Name.Contains(criteria.Filter) 
      || x.Document.Name.Contains(criteria.Filter)))) 

Это не работает, потому что любая строка, которая имеет нуль в поле, ссылающемся на BusinessPartner, Group или Document, не будет возвращен (с указанием внутреннего соединения).

Можно ли сделать то, что я хочу, с запросом <>()? Или с критериями?

ответ

1

Я не знаю про Query <>(), но с ICriteria вы можете управлять типом JOIN и получать сильный результат с помощью CreateAlias.

ICriterion conjunction = Restrictions.Conjunction(); 
conjunction.Add(Restrictions.Contains(criteria.Filter),"BusinessPartner.Name"); 
conjunction.Add(Restrictions.Contains(criteria.Filter),"Group.Name"); 
conjunction.Add(Restrictions.Contains(criteria.Filter),"Document.Name"); 

ICriteria query = ICriteria.CreateCriteria 
.CreateAlias("BusinessPartner", "BusinessPartner", JoinType.LeftOuterJoin) 
.CreateAlias("Group", "Group", JoinType.LeftOuterJoin) 
.CreateAlias("Document", "Document", JoinType.LeftOuterJoin) 
.Add(Restrictions.Between(criteria.DateFrom,criteria.DateTo),"Date") 
.Add(conjunction)); 

List<BusinessObject> results = query.List<BusinessObject>(); 
+0

Может потребоваться небольшой рефакторинг, я не в своем офисе. –

+0

Похоже, что это может сработать (попробуем завтра на работе, у меня здесь нет БД). Тем не менее, он делает то, что я пытался избежать, не используя SetResultTransformer - создавая псевдоним для каждого поля, когда я уже предоставил эту информацию в другой форме, записав сопоставления. Вот почему я предпочитаю использовать общий запрос, он использует сопоставления, чтобы автоматически присваивать значения правильным полям. Однако я могу все равно сделать это, потому что мне нужны внешние соединения. – svinja