Критерии NHibernate - Как фильтровать по комбинации свойств - PullRequest
3 голосов
/ 30 мая 2010

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

SELECT TOP 10 *
FROM Person
WHERE FirstName + ' ' + LastName LIKE '%' + @Term + '%'

ICriteria в NHibernate, который я в итоге использовал, был:

ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Sql(
    "FirstName + ' ' + LastName LIKE ?",
    "%" + term + "%",
    NHibernateUtil.String));
criteria.SetMaxResults(10);

Это работает отлично, но я не уверен, является ли это идеальным решением, так как я все еще изучаю API Критерии NHibernate. Каковы рекомендуемые альтернативы?

  • Есть ли что-то кроме Expression.Sql, которое выполняло бы ту же операцию? Я пытался Expression.Like, но не мог понять, как объединить имя и фамилию.
  • Должен ли я сопоставить свойство FullName с формулой "FirstName + '' + LastName" в классе отображения?
  • Должен ли я создать свойство FullName только для чтения для объекта домена и затем сопоставить его со столбцом?

Ответы [ 2 ]

13 голосов
/ 30 мая 2010

Вы можете сделать одно из следующих действий:

  • Если вы всегда работаете с полным именем, вероятно, лучше иметь одно свойство
  • Создать для этой цели свойство только для запроса (см. http://ayende.com/Blog/archive/2009/06/10/nhibernate-ndash-query-only-properties.aspx)
  • Выполните запрос на HQL, который лучше подходит для запросов произвольной формы (вероятно, он будет почти таким же, как ваш SQL)
  • Используйте правильные критерии на основе сущности:

Session.CreateCriteria<Person>()
       .Add(Restrictions.Like(
            Projections.SqlFunction("concat",
                                    NHibernateUtil.String,
                                    Projections.Property("FirstName"),
                                    Projections.Constant(" "),
                                    Projections.Property("LastName")),
            term,
            MatchMode.Anywhere))
0 голосов
/ 30 мая 2010

С чисто технической стороны у меня нет ответа, но учтите это: так как у вас есть только одно поле ввода для пользователя, чтобы ввести термин, вы не знаете, собирается ли он ввести 'foo bar' или 'bar foo' ... поэтому я бы порекомендовал это:

ICriteria criteria = Session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Like("FirstName",term, MatchMode.Anywhere) || Expression.Like("LastName",term, MatchMode.Anywhere));
criteria.SetMaxResults(10);
...