Entity?Framework?Core實(shí)現(xiàn)Like查詢?cè)斀?/h1>
更新時(shí)間:2022年02月22日 10:49:23 作者:Sweet-Tang
本文詳細(xì)講解了Entity?Framework?Core實(shí)現(xiàn)Like查詢的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
在Entity Framework Core 2.0中增加一個(gè)很酷的功能:EF.Functions.Like()
,最終解析為SQL中的Like
語(yǔ)句,以便于在 LINQ 查詢中直接調(diào)用。
不過Entity Framework 中默認(rèn)提供了StartsWith
、Contains
和EndsWith
方法用于解決模糊查詢,那么為什么還要提供EF.Functions.Like
,今天我們來重點(diǎn)說說它們之間的區(qū)別。
表結(jié)構(gòu)定義
在具體內(nèi)容開始之前,我們先簡(jiǎn)單說明一下要使用的表結(jié)構(gòu)。
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public override string ToString()
{
return $"{nameof(CategoryID)}: {CategoryID}, {nameof(CategoryName)}: {CategoryName}";
}
}
在 Category 類型定義了兩個(gè)字段:CategoryID、CategoryName。
public class SampleDbContext : DbContext
{
public virtual DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("數(shù)據(jù)庫(kù)連接字符串");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
EntityTypeBuilder<Category> entityTypeBuilder = modelBuilder.Entity<Category>();
entityTypeBuilder.ToTable("Category");
entityTypeBuilder.HasKey(e => e.CategoryID);
entityTypeBuilder.Property(e => e.CategoryID).UseSqlServerIdentityColumn();
}
}
我們使用 SampleDbContext 來訪問數(shù)據(jù)庫(kù)。
CategoryID CategoryName 1 Clothing 2 Footwear 3 Accessories
在數(shù)據(jù)庫(kù)的 Category 表中插入上面三行記錄。
EF.Functions.Like 使用示例
我們來看一個(gè)EF.Functions.Like()
查詢示例,查詢 CategoryName 字段中包括字符串 “t” 的數(shù)據(jù),傳遞的參數(shù)是 “%t%”:
[Fact]
public void Like()
{
using (var dataContext = new SampleDbContext()) {
var result= dataContext.Categories.Where(item => EF.Functions.Like(item.CategoryName, "%t%")).ToList();
foreach (var item in result) {
_testOutputHelper.WriteLine(item.CategoryName);
}
}
}
提示:在做一些示例演示時(shí),個(gè)人喜歡會(huì)用 Xunit + Resharper,這樣可以直接運(yùn)行對(duì)應(yīng)的示例,并且也可以直接輸出對(duì)應(yīng)的結(jié)果。
我們來看一下運(yùn)行的結(jié)果:

查詢的結(jié)果包含兩條數(shù)據(jù),這與我們預(yù)期結(jié)果一致。
字符串匹配模式
在這里,我暫且將StartsWith
、Contains
和EndsWith
方法稱之為字符串匹配模式。
您肯定在Entity Framework中使用過這些方式,我們還是簡(jiǎn)單說明一下這三個(gè)方法的作用:
StartsWith
:表示字符串的開頭是否與指定的字符串匹配;Contains
:表示指定的子串是否出現(xiàn)在此字符串中;EndsWith
:表示字符串的結(jié)尾是否與指定的字符串匹配;
我們可以通過Contains
方法實(shí)現(xiàn)與前一個(gè)示例一致的功能:
[Fact]
public void Contains()
{
using (var dataContext = new SampleDbContext())
{
var result = dataContext.Categories.Where(item => item.CategoryName.Contains("t")).ToList();
foreach (var item in result)
{
_testOutputHelper.WriteLine(item.CategoryName);
}
}
}
我們?cè)?code>Contains方法轉(zhuǎn)入?yún)?shù)“t” ,運(yùn)行的結(jié)果如下:

運(yùn)行結(jié)果與 Like
函數(shù)示例的結(jié)果是一致的。
在這里我只列舉了Contains
的示例,StartsWith
和EndsWith
的功能非常相似,我就不重復(fù)列舉了。
這兩個(gè)示例的運(yùn)行結(jié)果是一致的,那么微軟為什么要提供EF.Functions.Like()
方法呢?
通配符模糊查詢
我們知道在 T-SQL 語(yǔ)句中 Like 關(guān)鍵字支持 通配符 ,下面簡(jiǎn)單介紹支持的通配符:
通配符 說明 示例 % 包含零個(gè)或多個(gè)字符的任意字符串。 WHERE title LIKE '%computer%' 將查找在書名中任意位置包含單詞 "computer" 的所有書名。 _(下劃線) 任何單個(gè)字符。 WHERE au_fname LIKE '_ean' 將查找以 ean 結(jié)尾的所有 4 個(gè)字母的名字(Dean、Sean 等)。 [ ] 指定范圍 ([a-f]) 或集合 ([abcdef]) 中的任何單個(gè)字符。 WHERE au_lname LIKE '[C-P]arsen' 將查找以 arsen 結(jié)尾并且以介于 C 與 P 之間的任何單個(gè)字符開始的作者姓氏,
例如 Carsen、Larsen、Karsen 等。 [^] 不屬于指定范圍 ([a-f]) 或集合 ([abcdef]) 的任何單個(gè)字符。 WHERE au_lname LIKE 'de[^l]%' 將查找以 de 開始并且其后的字母不為 l 的所有作者的姓氏。
關(guān)于 Like 和通配符更多的知識(shí)請(qǐng)直接到MSDN中了解,鏈接地址:https://msdn.microsoft.com/zh-cn/library/ms179859(v=sql.110).aspx。
我們的將查詢關(guān)鍵字由 “t” 改為 “[a-c]”,再來看上面兩個(gè)示例分別運(yùn)行的結(jié)果:
EF.Functions.Like 查詢示例:

Contains 查詢示例:

上面運(yùn)行的結(jié)果,Like 查詢的結(jié)果返回三條記錄,而 Contains 查詢的結(jié)果無(wú)任何數(shù)據(jù)返回。
我們借助 SQL Server Profiler 分別捕獲這兩個(gè)示例實(shí)際生成的SQL查詢。
EF.Functions.Like 查詢生成的SQL語(yǔ)句:
SELECT [item].[CategoryID], [item].[CategoryName]
FROM [Category] AS [item]
WHERE [item].[CategoryName] LIKE N'%[a-c]%'
Contains 查詢生成的SQL語(yǔ)句:
SELECT [item].[CategoryID], [item].[CategoryName]
FROM [Category] AS [item]
WHERE CHARINDEX(N'[a-c]', [item].[CategoryName]) > 0
通過上面示例以及捕獲的SQL,我們可以得知,EF.Functions.Like()
查詢會(huì)被解釋成為 Like
,實(shí)際上是查詢字符串中包括 “a”、“b”、“c” 這三個(gè)字符中任何一個(gè)字符的數(shù)據(jù),而使用 Contains
查詢會(huì)被解析成為 CharIndex
函數(shù),實(shí)際是指查詢字符串中包括 “[a-c]” 的字符串。
提示: StartsWith
和EndsWith
分別會(huì)被解析成為Left
和Right
函數(shù),測(cè)試結(jié)果在這里不再做重復(fù)演示。
結(jié)論: 在EF Core中提供EF.Functions.Like()
方法的根本原因是在 TSQL 語(yǔ)句中 Like
關(guān)鍵字支持通配符,而在.Net中StartsWith
、Contains
和EndsWith
方法是不支持通配符的;
在EF Core中StartsWith
、Contains
和EndsWith
模糊查詢實(shí)際分別被解析成為Left
、CharIndex
和Right
,而不是Like
。
其它要點(diǎn)
通過上面的示例我們已經(jīng)說清楚了EF.Functions.Like()
方法和StartsWith
、Contains
和EndsWith
方法之間的區(qū)別,但是還有以下兩點(diǎn)需要說明。
EF Core StartsWith 優(yōu)化
如果使用StartWith
方法來實(shí)現(xiàn)模糊查詢,解析后的SQL語(yǔ)句會(huì)包括一個(gè)Like
查詢,您可能要說,剛才不是已經(jīng)講過嗎,StartsWith
、Contains
和EndsWith
方法解析后的SQL不是通過 Like
來查詢!先不要著急,我下面來說清楚這個(gè)問題。
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 捕獲實(shí)際生成的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語(yǔ)句中,即用到了Like
,也用到Left
函數(shù),這是為什么呢?
您可能知道在數(shù)據(jù)庫(kù)查詢時(shí),如果在某一個(gè)字段上使用函數(shù)是無(wú)法利用到索引的;在使用Left
,CharIndex
和Right
時(shí)是無(wú)法利用到索引的;而Like
查詢?cè)诎俜痔?hào)后置的情況下會(huì)利用到索引。關(guān)于數(shù)據(jù)庫(kù)的這些知識(shí),在博客園上有很多文章,我就不重復(fù)說明了。
結(jié)論: StartsWith
模糊查詢解析后的SQL用到Like
,這是因?yàn)?code>Like在百分號(hào)后置的是情況下會(huì)利用到索引,這樣查詢速度會(huì)更快。Contains
和EndsWith
模糊查詢解析后的SQL不包括Like
查詢,因?yàn)樵诜职偬?hào)前置的情況無(wú)法引用到索引。
關(guān)于Contains
和EndsWith
模糊查詢的測(cè)試,在這里不再重復(fù),您可以自己測(cè)試。
EF 6
在EF 6中,模糊查詢解析后的SQL語(yǔ)句與EF Core中略有不同,但是執(zhí)行的結(jié)果沒有區(qū)別。
我們?cè)贓F 6中分別捕獲StartsWith
、Contains
和EndsWith
解析后的SQL語(yǔ)句,不過我們搜索的關(guān)鍵字是:“[a-c]”,包含通配符。
StartsWith 查詢生成的SQL語(yǔ)句:
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語(yǔ)句:
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語(yǔ)句:
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
方法均會(huì)被解析為Like
查詢,但是是傳遞的參數(shù)由:“[a-c]”變?yōu)榱?ldquo;[a-b]”**,前面多了一個(gè)特殊符號(hào)**“”,并且查詢子句的后面還多了一部分 ESCAPE N'~'。
在MSDN上面有關(guān)ESCAPE
關(guān)鍵字的解釋,我們摘取其中一部分來說明:
使用 ESCAPE 子句的模式匹配搜索包含一個(gè)或多個(gè)特殊通配符的字符串。 例如,customers 數(shù)據(jù)庫(kù)中的 discounts 表可能存儲(chǔ)含百分號(hào) (%) 的折扣值。 若要搜索作為字符而不是通配符的百分號(hào),必須提供 ESCAPE 關(guān)鍵字和轉(zhuǎn)義符。 例如,一個(gè)樣本數(shù)據(jù)庫(kù)包含名為 comment 的列,該列含文本 30%。 若要搜索在 comment 列中的任何位置包含字符串 30% 的任何行,請(qǐng)指定 WHERE comment LIKE '%30!%%' ESCAPE '!' 之類的 WHERE 子句。 如果未指定 ESCAPE 和轉(zhuǎn)義符,則數(shù)據(jù)庫(kù)引擎將返回包含字符串 30 的所有行。
如果您想了解EF 6是如果過濾這些通配符的,可以在Github上面了解,鏈接地址:https://github.com/aspnet/EntityFramework6/blob/6.1.3/src/EntityFramework.SqlServer/SqlProviderManifest.cs#L164-L189。
結(jié)論:在EF 6中StartsWith
、Contains
和EndsWith
方法均會(huì)被解析為Like
查詢,但是如果出現(xiàn)了通配符,框架會(huì)結(jié)合ESCAPE
以及自身過濾功能將參數(shù)進(jìn)行轉(zhuǎn)義。
總結(jié)
通過上面的敘述,我們可以得到如下一些結(jié)論:
- 在EF Core中提供
EF.Functions.Like()
方法的根本原因是在 TSQL 語(yǔ)句中 Like
關(guān)鍵字支持通配符,而在.Net中StartsWith
、Contains
和EndsWith
方法是不支持通配符的; - 在EF Core中
StartsWith
、Contains
和EndsWith
模糊查詢分別被解析成為Left
、CharIndex
和Right
,而不是Like
。 - 在EF Core中
StartsWith
模糊查詢解析后的SQL用到Like
,這是因?yàn)?code>Like在百分號(hào)后置的是情況下會(huì)利用到索引,這樣查詢速度會(huì)更快; - 在EF 6中,
StartsWith
、Contains
和EndsWith
方法均會(huì)被解析為Like
查詢,但是如果出現(xiàn)了通配符,框架會(huì)結(jié)合ESCAPE
以及自身過濾功能將參數(shù)進(jìn)行轉(zhuǎn)義; - 在EF 6中,模糊查詢不支持通配符,這一點(diǎn)是因?yàn)槲覜]有找到對(duì)應(yīng)的解決方案!
到此這篇關(guān)于Entity Framework Core實(shí)現(xiàn)Like查詢的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:- Entity Framework Core使用控制臺(tái)程序生成數(shù)據(jù)庫(kù)表
- Entity Framework Core延遲加載(懶加載)用法
- Entity Framework Core中執(zhí)行SQL語(yǔ)句和存儲(chǔ)過程的方法介紹
- Entity Framework Core批處理SQL語(yǔ)句
- Entity Framework Core實(shí)現(xiàn)軟刪除與查詢過濾器
- Entity Framework Core生成列并跟蹤列記錄
- ASP.NET Core在WebApi項(xiàng)目中使用MiniProfiler分析Entity Framework Core
- Entity Framework Core工具使用命令行
- Entity?Framework?Core關(guān)聯(lián)刪除
- 詳解如何在ASP.NET Core中應(yīng)用Entity Framework
- Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫(kù)表
相關(guān)文章
-
.Net中的弱引用字典WeakDictionary和ConditionalWeakTable介紹
這篇文章介紹了.Net中的弱引用字典WeakDictionary和ConditionalWeakTable,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下 2022-06-06
-
asp.net中Response.Redirect與Server.Transfer的區(qū)別分析
一般來說如果需要在兩個(gè)頁(yè)面間共享數(shù)據(jù),而且數(shù)據(jù)量比較大的時(shí)候,用transfer會(huì)比較合適,在第二個(gè)頁(yè)面中可以直接使用前一頁(yè)面的數(shù)據(jù)。 2010-10-10
-
asp.net GridView控件鼠標(biāo)移動(dòng)某行改變背景顏色(方法一)
asp.net GridView控件鼠標(biāo)移動(dòng)某行改變背景顏色 2009-12-12
-
asp.net Oracle數(shù)據(jù)庫(kù)訪問操作類
asp.net Oracle數(shù)據(jù)庫(kù)訪問操作類,需要的朋友可以參考一下 2013-03-03
最新評(píng)論
在Entity Framework Core 2.0中增加一個(gè)很酷的功能:EF.Functions.Like()
,最終解析為SQL中的Like
語(yǔ)句,以便于在 LINQ 查詢中直接調(diào)用。
不過Entity Framework 中默認(rèn)提供了StartsWith
、Contains
和EndsWith
方法用于解決模糊查詢,那么為什么還要提供EF.Functions.Like
,今天我們來重點(diǎn)說說它們之間的區(qū)別。
表結(jié)構(gòu)定義
在具體內(nèi)容開始之前,我們先簡(jiǎn)單說明一下要使用的表結(jié)構(gòu)。
public class Category { public int CategoryID { get; set; } public string CategoryName { get; set; } public override string ToString() { return $"{nameof(CategoryID)}: {CategoryID}, {nameof(CategoryName)}: {CategoryName}"; } }
在 Category 類型定義了兩個(gè)字段:CategoryID、CategoryName。
public class SampleDbContext : DbContext { public virtual DbSet<Category> Categories { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("數(shù)據(jù)庫(kù)連接字符串"); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); EntityTypeBuilder<Category> entityTypeBuilder = modelBuilder.Entity<Category>(); entityTypeBuilder.ToTable("Category"); entityTypeBuilder.HasKey(e => e.CategoryID); entityTypeBuilder.Property(e => e.CategoryID).UseSqlServerIdentityColumn(); } }
我們使用 SampleDbContext 來訪問數(shù)據(jù)庫(kù)。
CategoryID | CategoryName |
---|---|
1 | Clothing |
2 | Footwear |
3 | Accessories |
在數(shù)據(jù)庫(kù)的 Category 表中插入上面三行記錄。
EF.Functions.Like 使用示例
我們來看一個(gè)EF.Functions.Like()
查詢示例,查詢 CategoryName 字段中包括字符串 “t” 的數(shù)據(jù),傳遞的參數(shù)是 “%t%”:
[Fact] public void Like() { using (var dataContext = new SampleDbContext()) { var result= dataContext.Categories.Where(item => EF.Functions.Like(item.CategoryName, "%t%")).ToList(); foreach (var item in result) { _testOutputHelper.WriteLine(item.CategoryName); } } }
提示:在做一些示例演示時(shí),個(gè)人喜歡會(huì)用 Xunit + Resharper,這樣可以直接運(yùn)行對(duì)應(yīng)的示例,并且也可以直接輸出對(duì)應(yīng)的結(jié)果。
我們來看一下運(yùn)行的結(jié)果:
查詢的結(jié)果包含兩條數(shù)據(jù),這與我們預(yù)期結(jié)果一致。
字符串匹配模式
在這里,我暫且將StartsWith
、Contains
和EndsWith
方法稱之為字符串匹配模式。
您肯定在Entity Framework中使用過這些方式,我們還是簡(jiǎn)單說明一下這三個(gè)方法的作用:
StartsWith
:表示字符串的開頭是否與指定的字符串匹配;Contains
:表示指定的子串是否出現(xiàn)在此字符串中;EndsWith
:表示字符串的結(jié)尾是否與指定的字符串匹配;
我們可以通過Contains
方法實(shí)現(xiàn)與前一個(gè)示例一致的功能:
[Fact] public void Contains() { using (var dataContext = new SampleDbContext()) { var result = dataContext.Categories.Where(item => item.CategoryName.Contains("t")).ToList(); foreach (var item in result) { _testOutputHelper.WriteLine(item.CategoryName); } } }
我們?cè)?code>Contains方法轉(zhuǎn)入?yún)?shù)“t” ,運(yùn)行的結(jié)果如下:
運(yùn)行結(jié)果與 Like
函數(shù)示例的結(jié)果是一致的。
在這里我只列舉了Contains
的示例,StartsWith
和EndsWith
的功能非常相似,我就不重復(fù)列舉了。
這兩個(gè)示例的運(yùn)行結(jié)果是一致的,那么微軟為什么要提供EF.Functions.Like()
方法呢?
通配符模糊查詢
我們知道在 T-SQL 語(yǔ)句中 Like 關(guān)鍵字支持 通配符 ,下面簡(jiǎn)單介紹支持的通配符:
通配符 | 說明 | 示例 |
---|---|---|
% | 包含零個(gè)或多個(gè)字符的任意字符串。 | WHERE title LIKE '%computer%' 將查找在書名中任意位置包含單詞 "computer" 的所有書名。 |
_(下劃線) | 任何單個(gè)字符。 | WHERE au_fname LIKE '_ean' 將查找以 ean 結(jié)尾的所有 4 個(gè)字母的名字(Dean、Sean 等)。 |
[ ] | 指定范圍 ([a-f]) 或集合 ([abcdef]) 中的任何單個(gè)字符。 | WHERE au_lname LIKE '[C-P]arsen' 將查找以 arsen 結(jié)尾并且以介于 C 與 P 之間的任何單個(gè)字符開始的作者姓氏, 例如 Carsen、Larsen、Karsen 等。 |
[^] | 不屬于指定范圍 ([a-f]) 或集合 ([abcdef]) 的任何單個(gè)字符。 | WHERE au_lname LIKE 'de[^l]%' 將查找以 de 開始并且其后的字母不為 l 的所有作者的姓氏。 |
關(guān)于 Like 和通配符更多的知識(shí)請(qǐng)直接到MSDN中了解,鏈接地址:https://msdn.microsoft.com/zh-cn/library/ms179859(v=sql.110).aspx。
我們的將查詢關(guān)鍵字由 “t” 改為 “[a-c]”,再來看上面兩個(gè)示例分別運(yùn)行的結(jié)果:
EF.Functions.Like 查詢示例:
Contains 查詢示例:
上面運(yùn)行的結(jié)果,Like 查詢的結(jié)果返回三條記錄,而 Contains 查詢的結(jié)果無(wú)任何數(shù)據(jù)返回。
我們借助 SQL Server Profiler 分別捕獲這兩個(gè)示例實(shí)際生成的SQL查詢。
EF.Functions.Like 查詢生成的SQL語(yǔ)句:
SELECT [item].[CategoryID], [item].[CategoryName] FROM [Category] AS [item] WHERE [item].[CategoryName] LIKE N'%[a-c]%'
Contains 查詢生成的SQL語(yǔ)句:
SELECT [item].[CategoryID], [item].[CategoryName] FROM [Category] AS [item] WHERE CHARINDEX(N'[a-c]', [item].[CategoryName]) > 0
通過上面示例以及捕獲的SQL,我們可以得知,EF.Functions.Like()
查詢會(huì)被解釋成為 Like
,實(shí)際上是查詢字符串中包括 “a”、“b”、“c” 這三個(gè)字符中任何一個(gè)字符的數(shù)據(jù),而使用 Contains
查詢會(huì)被解析成為 CharIndex
函數(shù),實(shí)際是指查詢字符串中包括 “[a-c]” 的字符串。
提示:
StartsWith
和EndsWith
分別會(huì)被解析成為Left
和Right
函數(shù),測(cè)試結(jié)果在這里不再做重復(fù)演示。
結(jié)論: 在EF Core中提供
EF.Functions.Like()
方法的根本原因是在 TSQL 語(yǔ)句中Like
關(guān)鍵字支持通配符,而在.Net中StartsWith
、Contains
和EndsWith
方法是不支持通配符的;
在EF Core中StartsWith
、Contains
和EndsWith
模糊查詢實(shí)際分別被解析成為Left
、CharIndex
和Right
,而不是Like
。
其它要點(diǎn)
通過上面的示例我們已經(jīng)說清楚了EF.Functions.Like()
方法和StartsWith
、Contains
和EndsWith
方法之間的區(qū)別,但是還有以下兩點(diǎn)需要說明。
EF Core StartsWith 優(yōu)化
如果使用StartWith
方法來實(shí)現(xiàn)模糊查詢,解析后的SQL語(yǔ)句會(huì)包括一個(gè)Like
查詢,您可能要說,剛才不是已經(jīng)講過嗎,StartsWith
、Contains
和EndsWith
方法解析后的SQL不是通過 Like
來查詢!先不要著急,我下面來說清楚這個(gè)問題。
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 捕獲實(shí)際生成的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語(yǔ)句中,即用到了Like
,也用到Left
函數(shù),這是為什么呢?
您可能知道在數(shù)據(jù)庫(kù)查詢時(shí),如果在某一個(gè)字段上使用函數(shù)是無(wú)法利用到索引的;在使用Left
,CharIndex
和Right
時(shí)是無(wú)法利用到索引的;而Like
查詢?cè)诎俜痔?hào)后置的情況下會(huì)利用到索引。關(guān)于數(shù)據(jù)庫(kù)的這些知識(shí),在博客園上有很多文章,我就不重復(fù)說明了。
結(jié)論:
StartsWith
模糊查詢解析后的SQL用到Like
,這是因?yàn)?code>Like在百分號(hào)后置的是情況下會(huì)利用到索引,這樣查詢速度會(huì)更快。Contains
和EndsWith
模糊查詢解析后的SQL不包括Like
查詢,因?yàn)樵诜职偬?hào)前置的情況無(wú)法引用到索引。
關(guān)于Contains
和EndsWith
模糊查詢的測(cè)試,在這里不再重復(fù),您可以自己測(cè)試。
EF 6
在EF 6中,模糊查詢解析后的SQL語(yǔ)句與EF Core中略有不同,但是執(zhí)行的結(jié)果沒有區(qū)別。
我們?cè)贓F 6中分別捕獲StartsWith
、Contains
和EndsWith
解析后的SQL語(yǔ)句,不過我們搜索的關(guān)鍵字是:“[a-c]”,包含通配符。
StartsWith 查詢生成的SQL語(yǔ)句:
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語(yǔ)句:
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語(yǔ)句:
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
方法均會(huì)被解析為Like
查詢,但是是傳遞的參數(shù)由:“[a-c]”變?yōu)榱?ldquo;[a-b]”**,前面多了一個(gè)特殊符號(hào)**“”,并且查詢子句的后面還多了一部分 ESCAPE N'~'。
在MSDN上面有關(guān)ESCAPE
關(guān)鍵字的解釋,我們摘取其中一部分來說明:
使用 ESCAPE 子句的模式匹配搜索包含一個(gè)或多個(gè)特殊通配符的字符串。 例如,customers 數(shù)據(jù)庫(kù)中的 discounts 表可能存儲(chǔ)含百分號(hào) (%) 的折扣值。 若要搜索作為字符而不是通配符的百分號(hào),必須提供 ESCAPE 關(guān)鍵字和轉(zhuǎn)義符。 例如,一個(gè)樣本數(shù)據(jù)庫(kù)包含名為 comment 的列,該列含文本 30%。 若要搜索在 comment 列中的任何位置包含字符串 30% 的任何行,請(qǐng)指定 WHERE comment LIKE '%30!%%' ESCAPE '!' 之類的 WHERE 子句。 如果未指定 ESCAPE 和轉(zhuǎn)義符,則數(shù)據(jù)庫(kù)引擎將返回包含字符串 30 的所有行。
如果您想了解EF 6是如果過濾這些通配符的,可以在Github上面了解,鏈接地址:https://github.com/aspnet/EntityFramework6/blob/6.1.3/src/EntityFramework.SqlServer/SqlProviderManifest.cs#L164-L189。
結(jié)論:在EF 6中
StartsWith
、Contains
和EndsWith
方法均會(huì)被解析為Like
查詢,但是如果出現(xiàn)了通配符,框架會(huì)結(jié)合ESCAPE
以及自身過濾功能將參數(shù)進(jìn)行轉(zhuǎn)義。
總結(jié)
通過上面的敘述,我們可以得到如下一些結(jié)論:
- 在EF Core中提供
EF.Functions.Like()
方法的根本原因是在 TSQL 語(yǔ)句中Like
關(guān)鍵字支持通配符,而在.Net中StartsWith
、Contains
和EndsWith
方法是不支持通配符的; - 在EF Core中
StartsWith
、Contains
和EndsWith
模糊查詢分別被解析成為Left
、CharIndex
和Right
,而不是Like
。 - 在EF Core中
StartsWith
模糊查詢解析后的SQL用到Like
,這是因?yàn)?code>Like在百分號(hào)后置的是情況下會(huì)利用到索引,這樣查詢速度會(huì)更快; - 在EF 6中,
StartsWith
、Contains
和EndsWith
方法均會(huì)被解析為Like
查詢,但是如果出現(xiàn)了通配符,框架會(huì)結(jié)合ESCAPE
以及自身過濾功能將參數(shù)進(jìn)行轉(zhuǎn)義; - 在EF 6中,模糊查詢不支持通配符,這一點(diǎn)是因?yàn)槲覜]有找到對(duì)應(yīng)的解決方案!
到此這篇關(guān)于Entity Framework Core實(shí)現(xiàn)Like查詢的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Entity Framework Core使用控制臺(tái)程序生成數(shù)據(jù)庫(kù)表
- Entity Framework Core延遲加載(懶加載)用法
- Entity Framework Core中執(zhí)行SQL語(yǔ)句和存儲(chǔ)過程的方法介紹
- Entity Framework Core批處理SQL語(yǔ)句
- Entity Framework Core實(shí)現(xiàn)軟刪除與查詢過濾器
- Entity Framework Core生成列并跟蹤列記錄
- ASP.NET Core在WebApi項(xiàng)目中使用MiniProfiler分析Entity Framework Core
- Entity Framework Core工具使用命令行
- Entity?Framework?Core關(guān)聯(lián)刪除
- 詳解如何在ASP.NET Core中應(yīng)用Entity Framework
- Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫(kù)表
相關(guān)文章
.Net中的弱引用字典WeakDictionary和ConditionalWeakTable介紹
這篇文章介紹了.Net中的弱引用字典WeakDictionary和ConditionalWeakTable,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06asp.net中Response.Redirect與Server.Transfer的區(qū)別分析
一般來說如果需要在兩個(gè)頁(yè)面間共享數(shù)據(jù),而且數(shù)據(jù)量比較大的時(shí)候,用transfer會(huì)比較合適,在第二個(gè)頁(yè)面中可以直接使用前一頁(yè)面的數(shù)據(jù)。2010-10-10asp.net GridView控件鼠標(biāo)移動(dòng)某行改變背景顏色(方法一)
asp.net GridView控件鼠標(biāo)移動(dòng)某行改變背景顏色2009-12-12asp.net Oracle數(shù)據(jù)庫(kù)訪問操作類
asp.net Oracle數(shù)據(jù)庫(kù)訪問操作類,需要的朋友可以參考一下2013-03-03