实体框架 EF.Functions.Like vs string.Contains
Posted
技术标签:
【中文标题】实体框架 EF.Functions.Like vs string.Contains【英文标题】:Entity framework EF.Functions.Like vs string.Contains 【发布时间】:2018-01-24 07:27:34 【问题描述】:我正在阅读实体框架核心2.0 https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-entity-framework-core-2-0/的公告
它说他们添加了新的 Sql 函数,例如 EF.Functions.Like
来执行 SQL LIKE
操作。
我想知道,EF.Functions.Like
和 string.Contains
/StartsWith
之间有什么区别?
例如:
var customers = context.Customers.Where(c => c.Name.StartsWith("a")); // Version A
var customers = context.Customers.Where(c => EF.Functions.Like(c.Name, "a%")); // Version B
这两个版本有什么区别?
EF 已经知道如何将string.Contains
/StartsWith
翻译成相应的 SQL 操作了,不是吗?
我能想到的唯一原因是 EF.Functions.Like 将允许更复杂的模式,例如 "a%b%"
(尽管这个可以写成 StartsWith("a") && Contains("b")
)
是这个原因吗?
【问题讨论】:
检查 SQL 语句。最有可能的是,它们是相同的。.StartsWith
被翻译成LIKE 'a%'
。另一方面,包含 将被转换为LIKE '%a%'
,这是一个非常糟糕的主意。 LIKE 'a%'
可以利用索引,因为它本质上是一个范围搜索。 LIKE '%a%'
虽然必须处理所有行以查找模式是否匹配
是的,就是这个原因
是的,正如我所怀疑的那样,如果他们为它提供一个扩展方法会好很多,c.Name.Like(...)
如果您没有为“like”提供字符大小写,它只会搜索您提供的字符或单词。也包含做同样的事情。但为了避免字符大小写,你可以使用如下: string k = "I like your style"; StringComparison stringComparison = StringComparison.CurrentCultureIgnoreCase; Console.WriteLine(k.IndexOf("your", stringComparison));
只是灵活性更高。阅读.Like('abc%def%ghi')
会更容易,然后尝试使用不同的树方法编写相同的内容。
【参考方案1】:
like 查询支持wildcard characters,因此在某些场景下与字符串扩展方法相比非常有用。
例如:如果我们要搜索所有以 'ri' 作为中间字符的 4 个字母名称,我们可以这样做 EF.Functions.Like(c.Name, "_ri_");
或获取所有以元音开头的城市的客户:
var customers = from c in context.Customers
where EF.Functions.Like(c.City, "[aeiou]%")
select c;
(请阅读@Tseng 的回答,了解它们如何以不同方式转换为 SQL 查询)
【讨论】:
还考虑阅读 #474 Query: Improve translation of String's StartsWith, EndsWith and Contains 线程,而不是出于此决定背后的灵活性原因。【参考方案2】:@adiga 的答案相当不完整,仅涵盖了部分用法差异。
但是,.StartsWith(...)
、.Contains(...)
和 .EndsWith(...)
转换为 SQL 的方式也与 EF.Functions.Like
不同。
例如,.StartsWith
被翻译为(string LIKE pattern + "%" AND CHARINDEX(pattern, string) = 1) OR pattern = ''
,而.Contains
被翻译为(CHARINDEX(pattern, string) > 0) OR pattern = ''
。
EF.Functions.Like
但是被翻译成string LIKE pattern [ESCAPE escapeChar]
。
这也可能对性能产生影响。以上对 EF Core SqlServer 提供程序有效。其他 EF Core 提供程序可能会以不同方式对其进行翻译。
【讨论】:
哪个更快? @ChrisGo 以我个人的经验,等号运算符 (==) 是最快的,其次是 StartsWith 和 EndsWith,它们与等号运算符很接近,并且 contains 是最慢且效率最低的,因为它需要逐个位置比较整个字符串的搜索词长度。当您可以使用等号运算符时,第二好的选择是用于搜索和过滤目的的 StartsWith。 @revobtz:不确定你是否意识到,这不是关于 C# 字符串操作,而是关于 SQL(以及使用这些操作的 Entity Framework Core 表达式如何转换为 SQL) @Tseng:我一直在谈论 SQL 和实体框架......即使这是在谈论字符串,它的行为仍然几乎相同,但当然你不会看到任何使用字符串时的性能差异,因为 sql 需要执行额外的操作来进行搜索过滤。我使用过很多数据库引擎 Sql Server、Oracle、mysql、MariaDB、Postgress、MongoDB,其中一些引擎我知道如何调整它们。 :)以上是关于实体框架 EF.Functions.Like vs string.Contains的主要内容,如果未能解决你的问题,请参考以下文章
Linq WHERE EF.Functions.Like - 为啥直接属性起作用而反射不起作用?