我从sql profiler复制了linq构建的sql查询,这里有什么令人讨厌的事情:
它的前缀为select ..columnNames ..(select ...columnNames .. from(select view from view from view) 注释:此处的2个选择语句是不必要的。
此查询需要14秒才能执行
当我删除最后一行,包含所有参数,如@ p_ linq _0 ..并在where条件中填充param值并执行完全相同的动态查询需要1秒或更少。即使从sql studio执行此查询也需要0秒。这是linq的蹩脚。
我可能会将此移至存储过程,但我现在害怕使用linq
经过进一步研究后我发现:
查询1:
exec sp_executesql N'SELECT * from TableView WHERE Id = @Id', N'@Id int', @Id = 1
查询2:
exec sp_executesql N'SELECT * from TableView WHERE Id = 1'
查询1需要12秒,查询2需要0秒。这解释了为什么linq查询很慢。所以现在,这是否意味着我应该总是使用存储过程或者我错过了什么?
为什么Microsoft无法修复Linq查询构建,解析该字符串并替换param值而不是将这些params作为参数传递给sp_executesql
是多么困难答案 0 :(得分:6)
我和你在一起。我的意思是,你可能会发现你发现这种灾难性性能的原因并找到补救措施。但实际上,这种事情发生在Linq to SQL上,并花费额外的时间来优化你的Linq语句,以便SQL查询在后端类型上的性能更加失败。 Linq应该让事情变得更容易。
我个人使用Linq-to-SQL或Entity Framework对单个记录执行CRUD操作。然后使用任何大的SELECT
语句,我将简单地编写一个存储过程,就像我一直在做的那样。这似乎是生产力和性能之间的良好折衷,对我来说效果很好。
编辑: 事实上,实体框架的人们预料到了这一点。实体框架与存储过程非常相似。你可以add a stored proc to your Entity Framework model获得所有那种强烈类型的善良。然后你可以从代码中调用那个存储过程。
答案 1 :(得分:0)
您应该构建Where谓词,动态取出特定于应用程序的daysRange 像这样
var query = from v in tableView
where v.Id == Id
orderby v.RDate descending
select v;
if(!daysRange.Equals("All"))
{
query = query.Where(v => v.RdDate >= fromDate && v.RDate <= toDate);
}
query.ToList();
答案 2 :(得分:0)
这样可行。
ParameterExpression parameterExpression = Expression.Parameter(typeof(TableView), "v");
Expression equalsExpression = Expression.Equal(Expression.Property(parameterExpression, "Id"), Expression.Constant(Id));
Expression<Func<TableView, bool>> predicate = Expression.Lamda<Func<TableView, bool>>(equalsExpression, parameter);
var query = from v in tableView
orderby v.RDate descending
select v;
if(!daysRange.Equals("All"))
{
query = query.Where(v => v.RdDate >= fromDate && v.RDate <= toDate);
}
query.Where(predicate).ToList();