2009-01-29 68 views
6

鉴于针对EF数据背景下,这个LINQ查询产生:SQL通过实体框架的字符串匹配

var customers = data.Customers.Where(c => c.EmailDomain.StartsWith(term)) 

你希望它产生这样的SQL,对不对?

SELECT {cols} FROM Customers WHERE EmailDomain LIKE @term+’%’ 

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

SELECT {cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1) 

你知道为什么吗?

而且,更换其中选择到:

c => c.EmailDomain.Substring(0, term.Length) == term 

它运行速度快10倍,但仍然会产生一些非常令人讨厌的SQL。

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

+0

你见过恶心的组装或MSIL你好看的LINQ或任何好的C#源代码后,如何得到?问题是如果它给出正确的结果,为什么我们需要打扰。 – 2011-04-12 04:10:02

+0

感谢关于用Substring替换StartsWith的提示 - 解决了与StartsWith版本不匹配空字符串作为前缀的问题。 – 2014-01-28 16:53:20

+0

[linq to entities generated sql]可能的副本(http://stackoverflow.com/questions/576803/linq-to-entities-generated-sql) – brechtvhb 2015-07-24 09:05:56

回答

3

原因是CharIndex比LIKE执行SQL更快,更干净。原因是,你可以有一些疯狂的“喜欢”条款。例如:

SELECT * FROM Customer WHERE EmailDomain LIKE 'abc%de%sss%' 

但是,在“CHARINDEX”功能(这基本上是“的IndexOf”)只处理发现一组字符的第一个实例...没有允许使用通配符。

因此,有你的答案:)

编辑:我只是想补充一点,我鼓励人们使用CHARINDEX在他们的SQL查询的东西,他们并不需要“喜欢”的。值得注意的是,尽管在SQL Server 2000中,“文本”字段可以使用LIKE方法,但不能使用CHARINDEX。

0

LIKE和CHARINDEX之间的表现似乎差不多,所以不应该是这个原因。一些讨论见herehere。 CAST也很奇怪,因为CHARINDEX返回一个int。

0

我同意这是不是更快,我正在从我们的数据库检索成千上万的行与我的名字的信。然而,我却发现你需要使用>而不是= ...所以使用

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) > 0) 

而不是

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1) 

这里是我的两个测试....

select * from members where surname like '%i%' --12 seconds 

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) > 0) --12 seconds 

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) = 1) --too few results