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 Collate,否则它将始终视为您的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 Collates的更多信息,请参阅SQL Server Collate区分大小写的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); }
然后做
添加迁移案例敏感
更新数据库
SQL Server中的条件在默认情况下不区分大小写。 通过将列的默认sortingSQL_Latin1_General_CP1_CI_AS
( SQL_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)
- 如何find活动的app.config文件的path?
- .NET提供了一个简单的方法将字节转换为KB,MB,GB等?
- 我如何在我的C#程序面板中运行另一个应用程序?
- 如何从文件中删除单个属性(例如ReadOnly)?
- C#获取%AppData%的path
- InvalidOperationException:无法parsing“Microsoft.AspNetCore.Http.IHttpContextAccessor”types的服务
- 你什么时候使用StringBuilder.AppendLine / string.Format与StringBuilder.AppendFormat?
- 事件处理程序是否停止发生垃圾回收?
- 何时不使用entity framework