【发布时间】:2015-07-29 05:22:42
【问题描述】:
我有一个控制器,它基本上通过 return View(result); 返回一个 IOrderedQueriable 对象;
关键是,当视图尝试执行该查询时,它会花费大量时间,并且最终会出现一些超时异常。我相信原因是因为在结果下创建的查询非常复杂。我想知道是否可以就如何改进我的 linq 查询提供一些建议。
这是我的丑陋和讨厌的查询:
public ActionResult FileList(string productName, string projectName)
{
var tagCount = (from l in db.FileDatas
from t in db.ProcessedFiles.Where(x => l.FileId == x.FileId &&
l.ProductId == x.ProductId &&
l.ProjectId == x.ProjectId &&
l.Product.Product1.Equals(productName))
.GroupBy(t => new { .ProductId, t.ProjectId, t.FileId, l.ExtensionId })
select new GroupedTagsRow
{
ProductName = l.Product.Product1,
ProjectName = l.Project.Project1,
FileName = l.File.File1,
Occurrences = t.Sum(x => x.Occurrences)
});
var unprocessedTags = db.UnProcessedTags
.Where(x => x.Product.Product1.Equals(productName) &&
x.Project.Project1.Equals(projectName) &&
x.TagId != 1);
var listOfFiles = db.FileDatas
.Where(x => x.Product.Product1.Equals(productName) &&
x.Project.Project1.Equals(projectName));
var result = listOfFiles
.GroupBy(file => file.File)
.Select(data => new File
{
FileName = data.FirstOrDefault().File.File1,
TotalTags = tagCount.Where(p => p.FileName.Equals(data.FirstOrDefault().File.File1)).Sum(x => x.Occurrences).ToString(),
UnprocessedTags = unprocessedTags.Where(p => p.File.File1.Equals(data.FirstOrDefault().File.File1)).DefaultIfEmpty().Count().ToString(),
})
.OrderBy(fileName => fileName.FileName);
return View(result);
}
上面的代码执行得非常快,我猜这是因为它只是自己生成查询。但是当它进入视图并尝试迭代结果时,它需要很长时间才能到达 foreach 循环。
@model IQueryable<File>
@{
ViewBag.Title = "File";
}
<h4>Number of files: <strong> @Model.Count() </strong></h4>
@foreach (var item in Model)
{
@RenderItem(item);
}
知道如何优化它吗?最后,我的查询返回大约 100 个 File 对象。但是对象内每个属性的初始化正在杀死系统......
谢谢!
【问题讨论】:
-
我可以看到杀死我的查询的操作是从 File 对象填充 TotalTags 和 UnprocessedTags 的两个操作
-
也许在您的操作方法开始构建结果对象之前尝试执行一些查询。例如
tagCount = <query here>.Select(..).ToList()。我认为这需要很多时间,因为每个子查询都是针对listOfFiles中的每个文件执行的 -
感谢您的回复,您的建议使事情变得更快,但我最终在 SQL 上编写了整个查询并创建了一些视图,然后我在我的 Web 应用程序中引用了这些视图。这使得技巧和执行要快得多! :)
标签: c# asp.net performance linq linq-to-sql