Сравнение с регистром LINQ to Entities

Это не чувствительное к регистру сравнение в LINQ с объектами:

Thingies.First(t => t.Name == "ThingamaBob"); 

Как я могу получить сравнение чувствительности к регистру с LINQ к объектам?

Это потому, что вы используете LINQ To Entities, который в конечном итоге преобразует ваши выражения Lambda в SQL-выражения. Это означает, что чувствительность к регистру находится во власти вашего SQL Server, который по умолчанию имеет SQL_Latin1_General_CP1_CI_AS Collation и не чувствителен к регистру.

Использование ObjectQuery.ToTraceString для просмотра сгенерированного SQL-запроса, который был фактически отправлен на SQL Server, раскрывает тайну:

 string sqlQuery = ((ObjectQuery)context.Thingies .Where(t => t.Name == "ThingamaBob")).ToTraceString(); 

Когда вы создаете запрос LINQ to Entities , LINQ to Entities использует анализатор LINQ для начала обработки запроса и преобразования его в дерево выражений LINQ. Дерево выражений LINQ затем передается API-интерфейсу объектов , который преобразует дерево выражений в дерево команд. Затем он отправляется поставщику магазина (например, SqlClient), который преобразует дерево команд в текст команды основной базы данных. Запрос выполняется в хранилище данных, и результаты материализуются в объекты объектов через службы объектов . Никакая логика не была вставлена ​​между ними, чтобы учитывать чувствительность к регистру. Поэтому независимо от того, в каком случае вы помещаете в свой предикат, он всегда будет рассматривать одно и то же на вашем SQL Server, если вы не измените ваши SQL Server Collates для этого столбца.

Решение на стороне сервера:

Поэтому лучшим решением было бы изменить сортировку столбца Name в таблице Thingies в COLLATE Latin1_General_CS_AS, которая чувствительна к регистру, выполнив это на вашем SQL Server:

 ALTER TABLE Thingies ALTER COLUMN Name VARCHAR(25) COLLATE Latin1_General_CS_AS 

Для получения дополнительной информации о SQL Server Collates рассмотрите SQL SERVER.

Клиентское решение:

Единственным решением, которое вы можете применить на стороне клиента, является использование LINQ to Objects для проведения еще одного сравнения, которое не кажется очень элегантным:

 Thingies.Where(t => t.Name == "ThingamaBob") .AsEnumerable() .First(t => t.Name == "ThingamaBob"); 

Вы можете добавить аннотацию [CaseSensitive] для EF6 + Code-first

Добавить эти classы

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] public class CaseSensitiveAttribute : Attribute { public CaseSensitiveAttribute() { IsEnabled = true; } public bool IsEnabled { get; set; } } public class CustomSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator { protected override void Generate(AlterColumnOperation alterColumnOperation) { base.Generate(alterColumnOperation); AnnotationValues values; if (alterColumnOperation.Column.Annotations.TryGetValue("CaseSensitive", out values)) { if (values.NewValue != null && values.NewValue.ToString() == "True") { using (var writer = Writer()) { //if (System.Diagnostics.Debugger.IsAttached == false) System.Diagnostics.Debugger.Launch(); // https://github.com/mono/entityframework/blob/master/src/EntityFramework.SqlServer/SqlServerMigrationSqlGenerator.cs var columnSQL = BuildColumnType(alterColumnOperation.Column); //[nvarchar](100) writer.WriteLine( "ALTER TABLE {0} ALTER COLUMN {1} {2} COLLATE SQL_Latin1_General_CP1_CS_AS {3}", alterColumnOperation.Table, alterColumnOperation.Column.Name, columnSQL, alterColumnOperation.Column.IsNullable.HasValue == false || alterColumnOperation.Column.IsNullable.Value == true ? " NULL" : "NOT NULL" //todo not tested for DefaultValue ); Statement(writer); } } } } } public class CustomApplicationDbConfiguration : DbConfiguration { public CustomApplicationDbConfiguration() { SetMigrationSqlGenerator( SqlProviderServices.ProviderInvariantName, () => new CustomSqlServerMigrationSqlGenerator()); } } 

Измените свой DbContext, добавьте

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention( "CaseSensitive", (property, attributes) => attributes.Single().IsEnabled)); base.OnModelCreating(modelBuilder); } 

Тогда сделайте

Add-Migration CaseSensitive

Обновление базы данных

на основе статьи https://milinaudara.wordpress.com/2015/02/04/case-sensitive-search-using-entity-framework-with-custom-annotation/ с исправлением ошибок

Условия WHERE в SQL Server по умолчанию нечувствительны к регистру. Сделайте регистр чувствительным к регистру, изменив сопоставления по умолчанию столбца ( SQL_Latin1_General_CP1_CI_AS ) на SQL_Latin1_General_CP1_CS_AS .

Хрупкий способ сделать это – с кодом. Добавьте новый файл миграции, а затем добавьте его внутри метода Up :

 public override void Up() { Sql("ALTER TABLE Thingies ALTER COLUMN Name VARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL"); } 

Но

Вы можете создать пользовательскую аннотацию под названием «CaseSensitive», используя новые функции EF6, и вы можете украсить свои свойства следующим образом:

 [CaseSensitive] public string Name { get; set; } 

В этом блоге объясняется, как это сделать.

Ответ, данный @Morteza Manavi, решает проблему. Тем не менее, для клиентского решения элегантный способ был бы следующим (добавив двойную проверку).

 var firstCheck = Thingies.Where(t => t.Name == "ThingamaBob") .FirstOrDefault(); var doubleCheck = (firstCheck.Name == model.Name) ? Thingies : null; 

Мне понравился ответ Мортезы, и он обычно предпочитает исправлять на стороне сервера. Для клиентской стороны я обычно использую:

 Dim bLogin As Boolean = False Dim oUser As User = (From c In db.Users Where c.Username = UserName AndAlso c.Password = Password Select c).SingleOrDefault() If oUser IsNot Nothing Then If oUser.Password = Password Then bLogin = True End If End If 

В основном, сначала проверяя, есть ли пользователь с требуемыми критериями, а затем проверьте, совпадает ли пароль. Немного длинный, но я чувствую, что его легче читать, когда может быть целая куча критериев.

Ни один из StringComparison.IgnoreCase работал для меня. Но это произошло:

 context.MyEntities.Where(p => p.Email.ToUpper().Equals(muser.Email.ToUpper())); 

Использовать string.Equals

 Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCulture); 

Кроме того, вам не нужно беспокоиться о null и возвращать только нужную вам информацию.

Используйте StringComparision.CurrentCultureIgnoreCase для нечувствительности к регистру.

 Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCultureIgnoreCase); 

Не уверен в EF4, но EF5 поддерживает это:

 Thingies .First(t => t.Name.Equals( "ThingamaBob", System.StringComparison.InvariantCultureIgnoreCase) 
  • Linq int to string
  • «Дата» не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности
  • Предложение "NOT IN" в LINQ to Entities
  • Entity Framework: запрос дочерних объектов
  • C # - код для заказа по свойству с использованием имени свойства в виде строки
  • Как выполнить сравнение даты в запросе EF?
  • Сколько Include я могу использовать в ObjectSet в EntityFramework для сохранения производительности?
  • большая проблема в преобразовании строки в datetime с использованием linq-to-entity
  • Указанный член типа «Дата» не поддерживается в LINQ to Exities Exception
  • Указанный член типа не поддерживается в LINQ to Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности
  • В LINQ для Entities поддерживаются только конструкторы и инициализаторы без параметров
  • Interesting Posts

    Виртуальная машина Java и CLR

    Программное обеспечение, отображающее время NTP-сервера

    Ручная установка 64-разрядных драйверов ODBC для доступа к MS Access при наличии 32-разрядного Office

    Аллен Голуб писал: «Вы никогда не должны использовать функции get / set», правильно ли он?

    как инициализировать ‘const std :: vector ‘ как ac array

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

    Создание глобально уникального идентификатора в Java

    Как создать экземпляр из строки в C #?

    Динамическая загрузка ресурсов Android

    Две системные зарезервированные разделы после чистой установки на новые диски

    Файл записи NDK для Android

    Свяжите новую запись с существующей формой

    Инструменты для поиска узких мест в конфигурации оборудования

    Обновление Node.js до последней версии

    Как указать атрибуты XML-сериализации для поддержки префиксов пространства имен во время десериализации в .NET?

    Давайте будем гением компьютера.