【问题标题】:Entity framework EF.Functions.Like vs string.Contains实体框架 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.Likestring.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') 会更容易,然后尝试使用不同的树方法编写相同的内容。

标签: c# entity-framework .net-core entity-framework-core


【解决方案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 查询)

【讨论】:

【解决方案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,其中一些引擎我知道如何调整它们。 :)
猜你喜欢
  • 1970-01-01
  • 2014-04-17
  • 2011-03-29
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 2010-11-12
  • 1970-01-01
相关资源
最近更新 更多