2010-09-13 2 views
1

Я ищу способ создания оператора OR в запросе для поиска определенного значения в одном поле таблицы, а также в другом поле объединенной таблицы. Это довольно просто в SQL, но я не могу понять, как это сделать в NHibernate. Я искал в Интернете, но примеры, которые я нахожу, довольно туманны для меня, и я считаю, что их трудно применить к моей конкретной реализации.NHibernate: запрос с оператором OR

У меня есть класс под названием «Сторона» со строковым полем, называемым ссылкой, которое является основной ссылкой. Новые требования требовали также возможности добавления большого количества побочных ссылок на сторону. Поэтому мне пришлось добавить еще один класс под названием PartyReference, который имеет отношение «много-к-одному» к партии.

Теперь с данной ссылкой я должен посмотреть ее значение как в этом основном поле ссылки, так и среди побочных ссылок. Но до тех пор, пока я не могу понять NHibernate, что КАК это поле должно соответствовать значению ИЛИ одному из других, я не могу заставить его работать.

Я сделал обходной путь, который выглядит, как это, но это некрасиво и глупо, так как там должен быть способ сказать «ИЛИ»:

public Party GetPartyOnAnyReference(string reference) 
     { 
      Party party; 

      ISession session = Factory.OpenSession(); 
      ITransaction tx = session.BeginTransaction(); 
      try 
      { 
       //first search on main reference 
       ICriteria criteria1 = session.CreateCriteria(typeof(Party)); 
       criteria1.Add(Restrictions.Eq("Reference", reference)); 
       IList<Party> parties1 = criteria1.List<Party>(); 
       party = parties1.Count > 0 ? parties1[0] : null; 

       //then try with side-references 
       if (party == null) 
       { 
        ICriteria criteria2 = session.CreateCriteria(typeof(Party)); 
        criteria2 
          .SetFetchMode("References", FetchMode.Eager) 
          .CreateCriteria("References") 
          .Add(Expression.Eq("Reference", reference)); 
        IList<Party> parties2 = criteria2.List<Party>(); 
        party = parties2.Count > 0 ? parties2[0] : null; 
       } 

       session.Close(); 
      } 
      catch (Exception e) 
      { 
       tx.Rollback(); 
       session.Close(); 

       if (e.GetType().ToString() == "NHibernate.ObjectNotFoundException") 
        party = null; 
       else throw; 
      } 
      return party; 
     } 

Я конечно понимаю, что также может решить эту проблему просто удалив основную ссылку из партийного класса alltogether и рассматривая ее наравне с другими ссылками, как PartyReference. Но на каком-то этапе мне придется использовать OR-запрос с NHibernate в любом случае, поэтому я могу просто решить его сейчас в этом конкретном случае.

Любые идеи?

ответ

4

Вы можете использовать Restrictions.Or или использовать дизъюнкцию для нескольких или.

session.CreateCriteria<Party>() 
    .CreateAlias("References", "r", JoinType.LeftOuterJoin) 
    .Add(Restrictions.Or(
     Restrictions.Eq("Reference", reference), 
     Restrictions.Eq("r.Reference", reference))) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Party>(); 
+0

Спасибо, миллион! Это было именно то изящное решение, которое я искал. Мне приходилось несколько раз запускать Unit Test, чтобы поверить своим собственным глазам. –

+0

С одним небольшим изменением: «LeftOuterJoin» - «JoinType.LeftOuterJoin» ... –