String.Equals() не работает по назначению
Я использую LINQ для поиска по одной из моих таблиц Entity Framework и поиска "группы" на основе имени. Имя является строкой и выглядит как Unicode (говорит, что это находится в edmx). У меня есть метод GetGroup()
, и я передаю имя для поиска. Отлаживая код, у меня уже есть группа с именем "Тест" в моей базе данных. Как только я перейду в группу под названием "TEST", я ожидаю, что она вернет "Тест" , который уже был в базе данных. По какой-то причине он не находит "Тест" и считает, что "ТЕСТ" не существует. Вот мой запрос, я не понимаю, почему он не работает. Пожалуйста, помогите.
"name" - это имя переданного в имени группы. Мой .Equals
работает, только если gr.Name
и имя то же самое. Если один символ является капиталом в одной из двух строк, то .Equals не работает. Я попытался использовать InvariantCultureIgnoreCase
, и это, похоже, не помогло. В случае, если кто-то спрашивает, MyLeagueId
и LeagueId
всегда будут совпадать, база данных будет настроена так, что может быть группа в другом лиге id. Я не думаю, что это проблема.
Group g = (from gr in this.DatabaseConnection.Groups
where gr.Name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
gr.LeagueId == this.MyLeagueId
select gr).FirstOrDefault();
Ответы
Ответ 1
При использовании LINQ to Entities он автоматически преобразует его в LINQ to SQL. И если поле базы данных, на котором выполняется .Equals, не имеет набора NOCASE (SQLite в моем примере), тогда он всегда будет чувствителен к регистру. В других словах база данных определяет, как выполнять сравнение строк, а не код.
Ответ 2
Сравнение строк с StringComparison.OrdinalIgnoreCase
работает в памяти или с IEnumerable<T>
. Вы пытаетесь использовать его с IQueryable<T>
, но поставщик вашего запроса не понимает его.
Это работает для меня:
db.Users.FirstOrDefault(
s => s.Username.Equals(username, StringComparison.OrdinalIgnoreCase)
);
Ответ 3
Сделал некоторые исследования. Вы не можете этого сделать. Сортировка (тип сравнения) определяется на уровне столбца таблицы. Вы не можете изменить его через EF. Если он определен как нечувствительный к регистру, тогда все поисковые запросы будут нечувствительны к регистру. Если он определен как чувствительный к регистру, то ваша единственная надежда - это ToUpper()
строки.
http://connect.microsoft.com/VisualStudio/feedback/details/435783/entity-framework-conceptual-model-doesnt-support-string-equals-via-linq
http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/3810aa67-f6fe-4624-a14b-eaaa0e05ddcd
EF4 Linq Oracle11g делает запросы не чувствительными к регистру
Сравнительное сравнение с LINQ to Entities
Ответ 4
Используйте String.Compare()
, поскольку он может быть переведен на Sql.
Здесь приведены некоторые примеры сопоставления строк в Linq, а также перевод Sql.
Ответ 5
Мне нравится ответ TravyGuy с технической точки зрения.
Для более прямого, практического ответа попробуйте использовать:
string.Compare(string A, string B, StringComparison.OrdinalIgnoreCase) == 0
Ответ 6
Попробуйте name.Equals(gr.Name, StringComparison.OrdinalIgnoreCase)
Если это сработает, проблема может быть с gr.Name
.
--- Редактировать ---
Я предполагаю, что gr.Name
не относится к типу System.string
. (поскольку String.Equals
дает вам ошибку == > из предыдущего сообщения)
произнесите этот снимок
(gr.Name as string).Equals(name, StringComparison.OrdinalIgnoreCase)
или
String.Equals((gr.Name as string), name, StringComparison.OrdinalIgnoreCase)