当使用带有变量的string.contains而不是硬编码字符串时,EF 4.0 Linq会生成奇怪的查询

时间:2012-07-17 09:04:59

标签: linq-to-sql c#-4.0 entity-framework-4

当我使用以下代码块(C#)时:

var query = context.Set.Where(o => o.Email.Contains("Mail@gmail.com"));
var stringQuery = ((System.Data.Objects.ObjectQuery)query).ToTraceString();

linq生成以下查询:

SELECT *
FROM [SET] AS [Extent1]
WHERE [Extent1].[Email] LIKE '%Mail@gmail.com%'

当我使用以下代码块时:

string email = "Mail@gmail.com";
var query = context.Set.Where(o => o.Email.Contains(email));
var stringQuery = ((System.Data.Objects.ObjectQuery)query).ToTraceString();

linq生成以下查询:

SELECT *
FROM [Set] AS [Extent1]
WHERE [Extent1].[Email] LIKE @p__linq__0 ESCAPE N'~'

如何让linq像第一种情况一样生成查询而不用字符串硬编码,而是作为字符串参数传递?

1 个答案:

答案 0 :(得分:1)

你看到的结果是应该的。原因是,Linq正确地将字符串文字标识为硬编码并假设它不受SQL注入和捕获(即它是常量,并且在运行延迟查询时不会是不同的值)。

类似地,它正确地识别变量可以变化,并且它可以是用户输入。它使用参数化查询,这是针对此类情况的建议/最佳实践。

但是,如果您确定要覆盖此最佳实践(因为您知道更好?)=)那么您可以遍历表达式树以查找变量访问权限并使用ConstantExpression替换节点。我相信这会导致linq像您观察到的那样对查询进行硬编码。

MSDN - Expression Tree Visitor

注意VisitMemberAccess方法,并查看ConstantExpression MemberExpression