Linq to Entities: использование ToLower () в полях NText

Я использую SQL Server 2005 с базой данных, чувствительной к регистру ..

В функции поиска мне нужно создать запрос Linq To Entities (L2E) с предложением «where», который сравнивает несколько строк с данными в базе данных по следующим правилам:

  1. Сравнение - это режим «Содержит», а не строгое сравнение: простой, поскольку строковый метод Contains () разрешен в L2E.
  2. Сравнение должно быть нечувствительным к регистру: я использую ToLower () для обоих элементов, чтобы выполнить нечувствительное сравнение.

Все это работает очень хорошо, но я столкнулся со следующим исключением: «Тип данных аргумента ntext недопустим для аргумента 1 нижней функции» в одном из моих полей.

Кажется, что поле является полем NText, и я не могу выполнить для него ToLower ().
Что я мог сделать, чтобы иметь возможность выполнить Contains () без учета регистра в этом поле NText?


person Julien N    schedule 12.03.2010    source источник


Ответы (3)


Никогда не используйте .ToLower() для сравнения без учета регистра. Вот почему:

  1. Возможно, это неправильно (ваша сортировка клиентов может быть, скажем, турецкой, а ваша сортировка БД - нет).
  2. Это очень неэффективно; Выпущенный SQL - это LOWER вместо = с сортировкой без учета регистра.

Вместо этого используйте StringComparison.OrdinalIgnoreCase или StringComparison.CurrentCultureIgnoreCase:

var q = from f in Context.Foos
        where f.Bar.Equals("hi", StringComparison.OrdinalIgnoreCase)
        select f;

Но для Contains() есть проблема: в отличие от Equals, StartsWith и т. Д., У него нет перегрузки для StringComparison аргумента. Почему? Хороший вопрос; спросите у Microsoft.

Это, в сочетании с ограничением SQL Server на LOWER, означает, что нет простого способа делать то, что вы хотите.

Возможные обходные пути могут включать:

  • Используйте полнотекстовый индекс и выполняйте поиск в рамках процедуры.
  • Используйте вместо них Equals или StartsWith, если это возможно для вашей задачи.
  • Изменить параметры сортировки столбца по умолчанию?
person Craig Stuntz    schedule 12.03.2010
comment
гул ... Я думаю, вы говорите мне, что использовать ToLower () неправильно, но у меня нет другого решения, так как: - Изменение сопоставления - это слишком большая работа и риск только для некоторых критериев поиска - Equals & StartsWith здесь не подойдет . Я думаю о преобразовании поля NText в NVarchar и ограничении пользовательского ввода ... В моем случае производительность не очень важна. - person Julien N; 12.03.2010
comment
Я просто пытаюсь рассказать вам, какие есть варианты, а не утверждаю, что какой-то идеальный вариант для вас существует ... - person Craig Stuntz; 12.03.2010

Используйте здесь лямбда-выражение и создайте промежуточный список, который может обрабатывать нижнее предложение.

var q = Context.Foos.ToList().Where(s => s.Bar.ToLower().Contains("hi"));

Не очень эффективно, но работает. Если у вас есть дополнительные предикаты в предложении where, это работает в ваших интересах:

var q = Context.Foos.Where(p => p.f1 == "foo" && p.f2 == "bar").
            ToList().Where(s => s.Bar.ToLower().Contains("hi"));
person Ira Klotzko    schedule 10.10.2012
comment
Это Linq to Entities: цель - сгенерировать соответствующий запрос SQL. Ваше решение захватит все строки таблицы (или строки, отфильтрованные по другим критериям), а затем применит фильтр. Действительно, это абсолютно неэффективно :). Но я допускаю, что это сработает! - person Julien N; 10.10.2012
comment
Я думал, что целью было подходящее linq для сущностей? С точки зрения эффективности ... Иногда, когда ваш клиент кричит, чтобы исправить эту чертову ошибку, а ваш босс постукивает пальцами, вызывая у вас вонючий глаз ... Эффективность и производительность сильно переоценены, за исключением тех случаев, когда это не так. То, что что-то можно оптимизировать, не означает, что это нужно делать. - person Ira Klotzko; 10.10.2012
comment
Согласен, я просто упомянул об этом, чтобы новые люди, использующие эту технику, знали, что она на самом деле делает (меня всегда удивляет, сколько людей используют L2E, не зная, что происходит под ней). Таким образом, с большими таблицами это может иметь значительное влияние на производительность / память. В моем случае производительность не имела значения. - person Julien N; 10.10.2012
comment
Безусловно, люди должны знать, хороший момент. Это не подходит для большого количества данных. - person Ira Klotzko; 15.10.2012

как мы знаем, это очень "глючная" ситуация. и это меня очень беспокоит.

Сегодня я решил создать представление как:

выберите * from tableName, где столбец типа '% key%'

затем загрузите это представление в EF.

жизнь налаживается!

person Benny Ae    schedule 05.03.2015