Подтвердить что ты не робот

LINQ Где игнорировать акцентуацию и случай

Каков самый простой способ фильтровать элементы с LINQ с помощью метода Where, игнорируя акцентуацию и случай?

До сих пор я мог игнорировать Casing, вызывая методы в свойствах, которые я не считаю хорошей идеей, потому что он вызывает тот же метод для каждого элемента (правильно?).

Итак, вот что я получил до сих пор:

var result = from p in People
             where p.Name.ToUpper().Contains(filter.ToUpper())
             select p;

Скажите, пожалуйста, если это хорошая практика, и самый простой способ игнорировать акцентуацию.

4b9b3361

Ответ 1

Чтобы игнорировать регистр и акценты (диакритики), вы можете сначала определить способ расширения следующим образом:

    public static string RemoveDiacritics(this String s)
    {
        String normalizedString = s.Normalize(NormalizationForm.FormD);
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < normalizedString.Length; i++)
        {
            Char c = normalizedString[i];
            if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                stringBuilder.Append(c);
        }

        return stringBuilder.ToString();
    }

(Изменено из Игнорирование акцентированных букв в сравнении строк)

Теперь вы можете запустить свой запрос:

string queryText = filter.ToUpper().RemoveDiacritics();

var result = from p in People
         where p.Name.ToUpper().RemoveDiacritics() == queryText
         select p;

Это нормально, если вы просто повторяете сборку на С#, но если вы используете LINQ to SQL, предпочтительнее избегать нестандартных методов (включая методы расширения) в вашем запросе LINQ. Это связано с тем, что ваш код не может быть преобразован в действительный SQL и, следовательно, работать на SQL Server со всей его прекрасной оптимизацией производительности.

Так как стандартного способа игнорирования акцентов в LINQ to SQL не существует, в этом случае я бы предложил изменить тип поля, который вы хотите искать, с учетом нечувствительности к регистру и акценту (CI_AI).

В вашем примере:

ALTER TABLE People ALTER COLUMN Name [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI

Теперь ваш запрос должен игнорировать акцентуацию и случай.

Обратите внимание, что вам нужно будет временно удалить любые уникальные ограничения в этом поле перед запуском указанного выше запроса, например

ALTER TABLE People DROP CONSTRAINT UQ_People_Name

Теперь ваш запрос LINQ будет выглядеть следующим образом:

var result = from p in People
         where p.Name == filter
         select p;

См. соответствующий вопрос здесь.

Ответ 2

Изменить сортировку:

ALTER TABLE dbo.MyTable 
ALTER COLUMN CharCol varchar(10)**COLLATE Latin1_General_CI_AS** NOT NULL;

Ответ 3

Вот некоторый код, который позволяет сравнивать игнорирование акцентуации:

Игнорирование букв с акцентом в сравнении строк

У меня будет пристойность не копировать код, так что автор может получить ответ на его ответ. Теперь, отвечая на ваш вопрос:

Вы получите этот кусок кода и будете его использовать следующим образом:

var result = from p in People
             where p.Name.ToUpper().Contains(RemoveDiacritics(filter.ToUpper()))
             select p;

Вы даже превращаете этот код в метод расширения. У меня есть:)