Entity Framework Core 大小写敏感处理

 

可以使用'StringComparison'吗?

在数据库查询操作中,不可避免去考虑字母大小写的问题,比如要在Movie表中查找“X-Men”这部电影,为了不区分字母大小写,按照Linq to memory的习惯,可能会写出如下代码:

DbContext.DbSet<Movie>
  .Where(item => string.Equals(item.Title, "X-Men", StringComparison.InvariantCultureIgnoreCase)

但是上述代码执行会报错,提示 'StringComparison'参数不支持。

InvalidOperationException: The LINQ expression 'DbSet<Movie>() .Where(m => string.Equals( a: m.Genre, b: __MovieGenre_0, comparisonType: InvariantCultureIgnoreCase))' could not be translated. 
Additional information: Translation of the 'string.Equals' overload with a 'StringComparison' parameter is not supported. 
See https://go.microsoft.com/fwlink/?linkid=2129535 for more information. 
Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. 
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

怎么解决这个问题呢?如果你用的是SQL server或MySQL,那么很简单,去掉“StringComparison.InvariantCultureIgnoreCase”这个参数就可以了,因为他们是默认大小写不敏感的。如果用的是大小写敏感的数据库,比如PostgreSQL,就需要做一些特殊处理了,后面会讲到。

对于这类问题有一个暴力的解决方法,就是按报错提示的那样在查询客户端做筛选:

DbContext.DbSet<Movie>
  .ToList()
  .Where(item => string.Equals(item.Title, "X-Men", StringComparison.InvariantCultureIgnoreCase)

这样做的本质是返回所有的Movie,然后在内存中做Title匹配查询(Linq to memory),而不是在DB中做Title的匹配查询,所以不会报 'StringComparison'参数不支持的错误。这种方法在绝大多数场景下是不推荐的,因为 1. 性能差,查询是在内存中不是在DB中,2. 占用内存,返回了整张表

 

为什么不能使用'StringComparison'?

前面讲到有的数据库是默认大小写不敏感的:SQL server,MySQL;有的数据库是默认大小写敏感的:PostgreSQL。那么数据库中大小写敏感与否是由什么控制的呢,排序规则(Collation,一组规则,用于确定文本值的排序和相等性比较方式,可以在数据库,表和列上创建排序规则,排序规则是隐式继承的,比如在数据库上创建了排序规则,没有在表上创建排序规则,那么表会默认使用数据库的排序规则,列同理)。因为EF core不知道数据库,表,列支持/应用了什么样的排序规则,所以'StringComparison'是没有意义的,EF core会将  string.Equals 转化成数据库的相等( = )操作,由数据库根据列上应用的排序规则来决定是否区分大小写。

 

如何在查询中设置区分大小写与否?

既然区分大小写是由排序规则决定的,我们可以通过在查询中指定排序规则的方式来来设置是否区分大小写,例如SQL Server默认是不区分大小写的,我们可以通过 EF.Functions.Collate 来指定一个大小写敏感的排序规则"SQL_Latin1_General_CP1_CS_AS"来达到精确匹配的目的

DbContext.DbSet<Movie>
    .Where(m => EF.Functions.Collate(item.Title, "SQL_Latin1_General_CP1_CS_AS") == "X-Men")

但是这种显示指定排序规则的方法也不是非常推荐的,因为他会导致索引匹配失败,进而影响查询性能。索引隐式继承列上的排序规则,当显示指定的排序规则和创建索引时指定的排序规则(PostgreSQL支持在创建索引时指定排序规则)或列的排序规则不一致时,会导致索引匹配失败,进而导致查询不能应用索引,这也是EF Core没有将'StringComparison'转换成排序规则的另一个原因。

因此一个相对完善的解决方案是,根据业务模型在列上指定合适的排序规则,而不是在代码中设置。如果数据库支持在列上创建多个索引,你也可以用显示指定排序规则的方式根据业务场景切换排序规则来匹配正确的索引。

 

参考文档:

https://learn.microsoft.com/en-us/ef/core/miscellaneous/collations-and-case-sensitivity

https://learn.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver16

https://www.postgresql.org/docs/current/collation.html

原文链接:https://www.cnblogs.com/Tiger-Lu/p/17311560.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Entity Framework Core 大小写敏感处理 - Python技术站

(0)
上一篇 2023年4月19日
下一篇 2023年4月19日

相关文章

  • C#中foreach实现原理详解

    C#中foreach实现原理详解 在C#语言中,foreach可以用于遍历数组、集合和自定义类型等可迭代对象。本文将详细介绍foreach的实现原理,让读者更深入地了解该语法的运行机制。 foreach语法 foreach语法的基本形式如下: foreach (var variable in expression) { // code block } 其中,…

    C# 2023年6月7日
    00
  • C#判断字符串中是否包含指定字符串及contains与indexof方法效率问题

    C#中判断一个字符串是否包含子字符串是一个常用的任务。本文将讲解如何使用C#的contains和indexof方法来实现这个任务,并探讨它们的效率问题。 contains方法 contains方法是String类中的一种方法,用于判断一个字符串是否包含指定的子字符串。代码示例如下: string str1 = "hello world";…

    C# 2023年6月8日
    00
  • LINQ(语言集成查询)使用案例

    LINQ使用案例 LINQ,全称为语言集成查询(Language Integrated Query),是.NET平台中的一项技术,通过使用可嵌入到C#和VB两种语言中的查询表达式,开发人员可以通过简单、一致的语法来查询各种数据源。 示例一:从数组中查询 以下是一个从整数数组中查询奇数的示例,使用LINQ语法查询: int[] numbers = { 0, 1…

    C# 2023年6月1日
    00
  • asp.net 截取Http请求的实现代码

    当我们需要对Http请求做一些特殊的处理时,我们可能需要截取Http请求。在ASP.NET中,我们可以通过编写HttpModule和HttpHandler来实现对Http请求的截取。 HttpModule实现截取Http请求 1.创建HttpModule 首先,我们需要创建一个继承自System.Web.IHttpModule接口的类。该接口具有两个方法:I…

    C# 2023年5月31日
    00
  • C#调用C类型dll入参为struct的问题详解

    下面是“C#调用C类型dll入参为struct的问题详解”的完整攻略: 1. 为什么C#调用C类型dll入参为struct会有问题? 在C中,结构体的内存布局与内存对齐非常重要,C编译器默认会对结构体进行内存对齐操作,而C#的结构体内存布局与C的不同,所以我们在C#代码中调用C类型dll时,需要手动将C#结构体转换为C中内存对齐后的结构体,确保与C的结构体一…

    C# 2023年5月31日
    00
  • C#6.0新语法示例详解

    C#6.0新语法示例详解攻略 简介 C#6.0是微软为.NET开发者带来的一个重要的版本,其中包含了很多新的语法特性,这些新特性可以让开发者更加方便地书写代码,提高代码的可读性和可维护性。 本篇攻略将会对C#6.0中的一些新语法特性进行详细讲解,包括:Null-conditional运算符、string的插值、nameof表达式、Auto-property初…

    C# 2023年5月15日
    00
  • C#使用SqlDataAdapter对象获取数据的方法

    下面详细讲解一下“C#使用SqlDataAdapter对象获取数据的方法”的完整攻略: 1. 准备工作 在使用SqlDataAdapter对象获取数据之前,需要先引用System.Data.SqlClient库。可以通过在程序代码中添加以下语句实现: using System.Data.SqlClient; 同时需要准备好连接数据库所需的参数,例如服务器名称…

    C# 2023年5月31日
    00
  • unity 切换场景不销毁物体问题的解决

    下面是详细讲解 “Unity切换场景不销毁物体问题的解决” 的完整攻略。 问题描述 在Unity中,切换场景时,场景中的物体通常都会被销毁并重新创建。但是,在某些情况下,我们希望在切换场景时不销毁某些物体,例如UI、游戏内人物等。那么该如何解决这个问题呢? 解决方法 方法一:使用DontDestroyOnLoad() Unity提供了DontDestroyO…

    C# 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部