Критерии NHibernate - Как фильтровать по комбинации свойств

Мне нужно было отфильтровать список результатов, используя комбинацию двух свойств. Простой 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 ответа

Решение

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

  • Если вы всегда работаете с полным именем, лучше всего иметь одно свойство
  • Для этого создайте свойство только для запроса (см. 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))

С чисто технической стороны у меня нет ответа, но учтите это: поскольку у вас есть только одно поле ввода для пользователя, чтобы ввести термин, вы не знаете, собирается ли он ввести '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);
Другие вопросы по тегам