LINQ to Entities区分大小写的比较

这不是在LINQ to Entities中区分大小写的比较:

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

我怎样才能实现区分大小写与LINQ to Entities的比较?

这是因为您正在使用LINQ To Entities ,最终将您的Lambdaexpression式转换为SQL语句。 这意味着大小写敏感性在您的SQL Server的摆布,它默认情况下具有SQL_Latin1_General_CP1_CI_ASsorting规则,并且不区分大小写。

使用ObjectQuery.ToTraceString查看实际提交给SQL Server的生成的SQL查询揭示了这个谜团:

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

在创buildLINQ to Entities查询时, LINQ to Entities利用LINQparsing器开始处理查询并将其转换为LINQexpression式树。 然后将LINQexpression式树传递给对象服务 API,该对象服务 API将expression式树转换为命令树。 然后发送到商店提供商(例如SqlClient),它将命令树转换为本地数据库命令文本。 查询在数据存储上执行,结果通过对象服务 实体化实体对象中 。 考虑到区分大小写之间没有逻辑关系。 因此,无论您将哪种情况放入谓词中,除非您更改该列的SQL Server Collat​​e,否则它将始终视为您的SQL Server。

服务器端解决scheme

因此,最好的解决scheme是将Thingies表中名称列的sorting规则 更改为COLLATE Latin1_General_CS_AS ,在您的SQL Server上运行此规则 ,这是区分大小写的:

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

有关SQL Server Collat​​es的更多信息,请参阅SQL Server Collat​​e区分大小写的SQL查询search

客户端解决scheme:

你可以在客户端应用唯一的解决scheme是使用LINQ to Objects来做另一个似乎不是很优雅的比较:

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

您可以为EF6 + Code-first添加[CaseSensitive]注释

添加这个类

 [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<CaseSensitiveAttribute, bool>( "CaseSensitive", (property, attributes) => attributes.Single().IsEnabled)); base.OnModelCreating(modelBuilder); } 

然后做

添加迁移案例敏感

更新数据库

基于文章https://milinaudara.wordpress.com/2015/02/04/case-sensitive-search-using-entity-framework-with-custom-annotation/与一些错误修复;

SQL Server中的条件在默认情况下不区分大小写。 通过将列的默认sortingSQL_Latin1_General_CP1_CI_ASSQL_Latin1_General_CP1_CI_AS )更改为SQL_Latin1_General_CP1_CI_AS来区分大小写。

脆弱的方式是使用代码。 添加一个新的迁移文件,然后将其添加到Up方法中:

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

您可以使用新的EF6function创build名为“CaseSensitive”的自定义注释,并且可以像这样修饰您的属性:

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

这篇博文解释了如何做到这一点。

@Morteza Manavi给出的答案解决了这个问题。 不过,对于客户端解决scheme来说 ,一个优雅的方法是如下(添加一个双重检查)。

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

我喜欢Morteza的答案,并通常宁愿修复服务器端。 对于客户端我通常使用:

 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)