由Entity Framework生成的SQL用于字符串匹配

tha*_*att 7 sql entity-framework

给定针对EF数据上下文的linq查询:

var customers = data.Customers.Where(c => c.EmailDomain.StartsWith(term))
Run Code Online (Sandbox Code Playgroud)

你希望它能像这样产生SQL,对吗?

SELECT {cols} FROM Customers WHERE EmailDomain LIKE @term+’%’
Run Code Online (Sandbox Code Playgroud)

嗯,实际上,它确实是这样的:

SELECT {cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1)
Run Code Online (Sandbox Code Playgroud)

你知道为什么吗?

另外,将Where选择器替换为:

c => c.EmailDomain.Substring(0, term.Length) == term
Run Code Online (Sandbox Code Playgroud)

它的运行速度提高了10倍,但仍会产生一些非常令人讨厌的SQL.

注意: Linq to SQL正确地将StartsWith转换为Like {term}%,并且nHibernate具有专用的LikeExpression.

Tim*_*uri 2

原因是 CharIndex 对于 SQL 来说比 LIKE 执行起来更快、更干净。原因是,你可以有一些疯狂的“LIKE”子句。例子:

SELECT * FROM Customer WHERE EmailDomain LIKE 'abc%de%sss%'
Run Code Online (Sandbox Code Playgroud)

但是,“CHARINDEX”函数(基本上是“IndexOf”)仅处理查找一组字符的第一个实例......不允许使用通配符。

所以,这就是你的答案:)

编辑:我只是想补充一点,我鼓励人们在 SQL 查询中使用 CHARINDEX 来处理他们不需要“LIKE”的事情。值得注意的是,在 SQL Server 2000 中...“文本”字段可以使用LIKE方法,但不能使用 CHARINDEX。

  • 虽然 Like 可能比 CharIndex 慢,但在 StartsWith 上下文中使用时它要快得多(即 Like {term}%)。在这种情况下,查询优化器能够利用现有索引。 (6认同)