是否可以阻止LINQ在查询中使用变量而是使用字符串文字?

时间:2011-06-13 01:42:15

标签: sql-server linq

我有一个LINQ查询,它有很多变量,生成的SQL看起来像:

exec sp_executesql N'SELECT col1, col2
FROM MyTable [t3]
WHERE 
  (([t3].[col1] = @p0) AND ([t3].[col2] = @p1))
  OR (([t3].[col1] = @p2) AND ([t3].[col2] = @p3))
  ...
N'@p0 varchar(32),@p1 varchar(32),@p2 varchar(32),@p3 varchar(32),...
,@p0='0',@p1='1',@p2='2',@p3='3',...

只要没有太多变量,例如150或更少,这就可以正常工作。但是当变量太多时,查询会显着减慢。

如果我有相同的查询,除了没有变量,例如:

SELECT col1, col2
FROM MyTable [t3]
WHERE
  (([t3].[col1] = '0') AND ([t3].[col2] = '1'))
  OR (([t3].[col1] = '2') AND ([t3].[col2] = '3'))
  ...

然后查询工作正常,即使有很多OR条件。

虽然我认为这确实是一个问题,当变量太多时SQL Server表现不佳,我想知道我是否可以通过不生成的SQL包含对变量的引用来解决LINQ中的这个问题,而是使用字符串文字

我意识到我可以通过不使用LINQ来解决这个问题,而是自己构建SQL,但希望有一个LINQ解决方案。

此外,虽然这个问题是关于LINQ的,但如果有一个加速查询涉及SQL Server的解决方案,我也会对此感兴趣。我应该补充一点,我在SQL Server 2005中看到了这个问题。

感谢您的帮助, 埃里克

3 个答案:

答案 0 :(得分:2)

问题非常广泛。 LINQ本身可能与您的查询性能无关。

如果查询中有很多OR,那么这就是SQL查询优化器对使用哪个索引感到困惑的原因。

在我看来,您首先需要关注SQL查询优化,添加适当的索引。当SQL查询被优化时,您将不会遇到LINQ问题。

[编辑]

如果使用字符串文字,最终可能会导致性能下降,因为SQL查询优化器将无法重用查询计划。每个查询都会触发新的查询计划生成。

答案 1 :(得分:2)

我不相信。事实上,Linq的一个功能是它可以防止用户Sql Injection攻击。

如果将查询参数加载到表中,然后将查询作为对表的连接运行,则可能会有更好的性能。

答案 2 :(得分:0)

正如其他人所说,参数不是问题。无论查询是否参数化,where子句中的许多OR都会混淆SQL Server。

一种解决方法是将查询更改为UNION查询,每个OR使用一个UNION。

E.g:

select ... from MyTable as t0 where t0.col1 = 0 and t0.col2 = 1
  union all
select ... from MyTable as t1 where t1.col1 = 2 and t0.col2 = 3

您可以使用LINQ .Union方法轻松构建类似于循环中的查询:

List<Tuple<int, int>> IDPairs = new List<Tuple<int, int>> { new Tuple<int, int>(0,1), new Tuple<int, int>(2,3) }

IQueryable<MyTable> query = null;
foreach (Tuple<int, int> IDs in IDPairs)
{
  if (query == null)
  {
    query = dc.MyTable.Where(w => w.Col1 == IDs.Item1 && w.Col2 == IDs.Item2);
  }
  else
  {
    query = query.Union(dc.MyTable.Where(w => w.Col1 == IDs.Item1 && w.Col2 == IDs.Item2));
  }
}

var result = query.ToList();