【问题标题】:EF 4.0 Linq generates weird query when using string.contains with a variable instead of hard coded string当使用带有变量而不是硬编码字符串的 string.contains 时,EF 4.0 Linq 会生成奇怪的查询
【发布时间】:2012-07-17 20:53:25
【问题描述】:

当我使用以下代码块(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:5

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


【解决方案1】:

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

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

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

MSDN - Expression Tree Visitor

注意VisitMemberAccess方法,看看ConstantExpressionMemberExpression

【讨论】:

  • 我想要实现的只是更好的性能,服务器回复第一个查询的时间是 70 毫秒,第二个是 344 毫秒。在传递之前不知道字符串的值有什么方法可以实现更好的性能?
  • 有趣。你能连续再现性能差异吗?你能创建一个显示这个的小型测试项目吗?两者之间的唯一区别应该是评估表达式所需的时间。如果是这种情况,请查看compiled queries。希望他们有所帮助!
  • 基本上你所需要的只是一个数据库,其中包含一个表,其中至少有一个类型为 varchar 或 nvarchar 的列,并执行 2 个与 post 中的查询格式相同的查询。只是不要忘记在运行查询之前包括客户统计信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 2012-06-05
  • 2021-05-03
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多