HTML5技术

Entity Framework Core Like 查询揭秘 - Sweet-Tang(2)

字号+ 作者:H5之家 来源:H5之家 2017-09-13 12:05 我要评论( )

通过上面示例以及捕获的SQL,我们可以得知,EF.Functions.Like() 查询会被解释成为 Like,实际上是查询字符串中包括 “a”、“b”、“c” 这三个字符中任何一个字符的数据,而使用 Contains 查询会被解析成为 CharI

通过上面示例以及捕获的SQL,我们可以得知,EF.Functions.Like() 查询会被解释成为 Like,实际上是查询字符串中包括 “a”、“b”、“c” 这三个字符中任何一个字符的数据,而使用 Contains 查询会被解析成为 CharIndex 函数,实际是指查询字符串中包括 “[a-c]” 的字符串。

提示: StartsWith和EndsWith分别会被解析成为Left和Right函数,测试结果在这里不再做重复演示。

结论: 在EF Core中提供EF.Functions.Like()方法的根本原因是在 TSQL 语句中 Like 关键字支持通配符,而在.Net中StartsWith、Contains和EndsWith方法是不支持通配符的;
在EF Core中StartsWith、Contains和EndsWith模糊查询实际分别被解析成为Left、CharIndex和Right,而不是Like。

其它要点

通过上面的示例我们已经说清楚了EF.Functions.Like()方法和StartsWith、Contains和EndsWith方法之间的区别,但是还有以下两点需要说明。

EF Core StartsWith 优化

如果使用StartWith方法来实现模糊查询,解析后的SQL语句会包括一个Like查询,您可能要说,刚才不是已经讲过吗,StartsWith、Contains和EndsWith方法解析后的SQL不是通过 Like 来查询!先不要着急,我下面来说清楚这个问题。

StartsWith 查询示例:

[Fact] public void StartsWith() { using (var dataContext = new SampleDbContext()) { var result = dataContext.Categories.Where(item => item.CategoryName.StartsWith("Clo")).ToList(); foreach (var item in result) { _testOutputHelper.WriteLine(item.CategoryName); } } }

借助 SQL Server Profiler 捕获实际生成的SQL查询:

SELECT [item].[CategoryID], [item].[CategoryName] FROM [Category] AS [item] WHERE [item].[CategoryName] LIKE N'Clo' + N'%' AND (LEFT([item].[CategoryName], LEN(N'Clo')) = N'Clo')

在SQL语句中,即用到了Like,也用到Left函数,这是为什么呢?

您可能知道在数据库查询时,如果在某一个字段上使用函数是无法利用到索引的;在使用Left,CharIndex和Right时是无法利用到索引的;而Like查询在百分号后置的情况下会利用到索引。关于数据库的这些知识,在博客园上有很多文章,我就不重复说明了。

结论: StartsWith模糊查询解析后的SQL用到Like,这是因为Like在百分号后置的是情况下会利用到索引,这样查询速度会更快。Contains和EndsWith模糊查询解析后的SQL不包括Like查询,因为在分百号前置的情况无法引用到索引。

关于Contains和EndsWith模糊查询的测试,在这里不再重复,您可以自己测试。

EF 6

在EF 6中,模糊查询解析后的SQL语句与EF Core中略有不同,但是执行的结果没有区别。

我们在EF 6中分别捕获StartsWith、Contains和EndsWith解析后的SQL语句,不过我们搜索的关键字是:“[a-c]”,包含通配符。

StartsWith 查询生成的SQL语句:

SELECT [Extent1].[CategoryID] AS [CategoryID], [Extent1].[CategoryName] AS [CategoryName] FROM [dbo].[Category] AS [Extent1] WHERE [Extent1].[CategoryName] LIKE N'~[a-c]%' ESCAPE N'~'

Contains 查询生成的SQL语句:

SELECT [Extent1].[CategoryID] AS [CategoryID], [Extent1].[CategoryName] AS [CategoryName] FROM [dbo].[Category] AS [Extent1] WHERE [Extent1].[CategoryName] LIKE N'%~[a-c]%' ESCAPE N'~'

EndsWith 查询生成的SQL语句:

SELECT [Extent1].[CategoryID] AS [CategoryID], [Extent1].[CategoryName] AS [CategoryName] FROM [dbo].[Category] AS [Extent1] WHERE [Extent1].[CategoryName] LIKE N'%~[a-c]' ESCAPE N'~'

StartsWith、Contains和EndsWith方法均会被解析为Like查询,但是是传递的参数由:“[a-c]”变为了“~[a-b]”,前面多了一个特殊符号“~”,并且查询子句的后面还多了一部分 ESCAPE N'~'。

在MSDN上面有关ESCAPE关键字的解释,我们摘取其中一部分来说明:

使用 ESCAPE 子句的模式匹配
搜索包含一个或多个特殊通配符的字符串。 例如,customers 数据库中的 discounts 表可能存储含百分号 (%) 的折扣值。 若要搜索作为字符而不是通配符的百分号,必须提供 ESCAPE 关键字和转义符。 例如,一个样本数据库包含名为 comment 的列,该列含文本 30%。 若要搜索在 comment 列中的任何位置包含字符串 30% 的任何行,请指定 WHERE comment LIKE '%30!%%' ESCAPE '!' 之类的 WHERE 子句。 如果未指定 ESCAPE 和转义符,则数据库引擎将返回包含字符串 30 的所有行。

如果您想了解EF 6是如果过滤这些通配符的,可以在Github上面了解,链接地址:。

结论:在EF 6中StartsWith、Contains和EndsWith方法均会被解析为Like查询,但是如果出现了通配符,框架会结合ESCAPE以及自身过滤功能将参数进行转义。

总结

通过上面的叙述,我们可以得到如下一些结论:

作者:Sweet Tang
本文地址:
欢迎转载,请在明显位置给出出处及链接。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • ASP.NET Core 运行原理解剖[5]:Authentication - 雨の夜

    ASP.NET Core 运行原理解剖[5]:Authentication - 雨の夜

    2017-09-11 11:16

  • .NET Core多平台开发体验[4]: Docker - Artech

    .NET Core多平台开发体验[4]: Docker - Artech

    2017-09-07 11:57

  • .NET Core 2.0应用程序大小减少50% - LineZero

    .NET Core 2.0应用程序大小减少50% - LineZero

    2017-09-06 08:05

  • ASP.NET Core MVC – Tag Helper 组件 - Sweet-Tang

    ASP.NET Core MVC – Tag Helper 组件 - Sweet-Tang

    2017-09-01 17:02

网友点评
e