2011-07-15 1 views
5

Я пытаюсь преобразовать следующий SQL в NHibernate:Нечеткий поиск на каскадных Полное имя с помощью NHibernate

SELECT * FROM dbo.Customer 
WHERE FirstName + ' ' + LastName LIKE '%' + 'bob smith' + '%' 

Я пытался сделать что-то вроде этого, но он не работает:

name = "%" + name + "%"; 

var customers = _session.QueryOver<Customer>() 
      .Where(NHibernate.Criterion.Restrictions.On<Customer>(c => c.FirstName + ' ' + c.LastName).IsLike(name)) 
      .List(); 

То, что я в основном пытаюсь сделать, - это поиск имени клиента в текстовом поле со значением примера «bob smith» и для его поиска в базе данных с использованием выражения LIKE в SQL выше.

Если я собираюсь неправильно искать столбцы FirstName и LastName, пожалуйста, помогите мне с альтернативой, но приведенный выше SQL-запрос доставит мне то, что мне нужно.

Update 2 решения:

Так что я в настоящее время нашел два решения этой проблемы. Один из них - использовать API критериев. В следующем посте есть ответ, который отлично работает: https://stackoverflow.com/a/2937100/670028

Другое решение, которое я нашел благодаря одному из моих полезных сотрудников, которые предложили использовать проекцию LINQ и анонимные типы. Вот решение с помощью LINQ:

var customers = session.Query<Customer>() 
    .Select(x => new { FullName = x.FirstName + " " + x.LastName, Customer = x }) 
    .Where(x => x.FullName.Contains("Bob Smith")) 
    .Select(x => x.Customer) 
    .ToList(); 
+0

Вы должны использовать 'Restrictions.Like' на проекции, используя concat sqlfunction. Я не думаю, что NH достаточно умен, чтобы построить для вас строчную конкатентную проекцию. – dotjoe

+0

Обновление: я обнаружил, что код NHibernate в этом случае слишком запутан, и просто пошел с хранимой процедурой. Я действительно стараюсь избегать хранимых процедур в максимально возможной степени, но иногда просто проще запускать sql самостоятельно. –

ответ

10

NHibernate не в состоянии перевести выражение в SQL заявление, потому что это не делает знать, что делать с c => c.FirstName + '' + c.LastName. Решение может быть переписывания это что-то вроде этого:

Session.CreateCriteria<Customer>() 
    .Add(Restrictions.Like(
    Projections.SqlFunction("concat", 
          NHibernateUtil.String, 
          Projections.Property("FirstName"), 
          Projections.Constant(" "), 
          Projections.Property("LastName")), 
    "Bob Whiley", 
    MatchMode.Anywhere)) 
+0

Я повторно просмотрел этот пост и пробовал этот код, и хотя он не работал правильно, он заставил меня на правильном пути найти другие решения. Следующее решение из другого ответа StackOverflow работало отлично, просто подумал, что я поделюсь: http://stackoverflow.com/a/2937100/670028 –

+0

привет, randy, если вы его работаете, вы можете отредактировать сообщение, чтобы исправить ответ, а затем отметьте это как правильный ответ, чтобы поделиться им с миром. – Peter

0

Я думаю, что это что-то вроде этого:

.С (с => c.IsLike (c.FirstName + '' + c.LastName))

Потому что вы не сравниваете правильные значения так, как вы это делаете прямо сейчас.

0

Я могу попробовать это:

query.Where(Restrictions.On<MyType>(x => x.Field).IsLike(StringToSearch)) 

Если это слишком Complexe с QueryOver или Criteria API можно использовать синтаксис HQL

1

Если вы хотите, чтобы ваш код, как сильно типизированных, как это возможно, вот как я достиг. Мне нужно было использовать его в дизъюнкции. Надеюсь, это поможет кому-то!

var disjunction = new Disjunction(); 
var fullNameProjection = Projections.SqlFunction(
    "concat", 
    NHibernateUtil.String, 
    Projections.Property<UserProfile>(x => x.FirstName), 
    Projections.Constant(" "), 
    Projections.Property<UserProfile>(x => x.LastName) 
    ); 
var fullNameRestriction = Restrictions.Like(fullNameProjection, searchText, MatchMode.Anywhere); 
disjunction.Add(fullNameRestriction); 

 Смежные вопросы

  • Нет связанных вопросов^_^