MVC应用程序中的表联接非常缓慢
本文关键字:非常 缓慢 应用程序 MVC | 更新日期: 2023-09-27 18:29:36
我有点不明白为什么我的MVC应用程序中的一个ASP视图运行如此缓慢。
我在控制器中使用linq选择一些数据。这运行得很快:
public ActionResult Progress(int ID)
{
var reviewitems = from ri in db.ReviewItems
where ri.Enrolment.Course.LearningArea.LearningAreaID == ID && ri.Review.ReviewSeries.StartDate < DateTime.Now && ri.Review.ReviewSeries.EndDate > DateTime.Now && ri.Progress < 2
select ri;
return View("Progress", reviewitems);
}
然后,我在ASP视图中执行foreach循环,遍历已传递给视图的"reviewitem"类型数据的每一行。同样,这很快:
<%foreach (var ri in Model)
{ %>
<tr>
<td><%= ri.Progress %></td>
</tr>
<%} %>
我需要更多的信息来显示,所以我需要加入"复习"表(再次给出快速结果),然后加入"学生"表。这就是问题所在,它开始需要30秒以上的时间:
<%foreach (var ri in Model)
{ %>
<tr>
<td><%= ri.Review.Student.Surname %></td>
</tr>
<%} %>
每个复习项目都链接到一个独特的学生,所以我不明白为什么要花这么长时间。有人知道我应该从哪里开始寻找为什么它如此缓慢吗?据推测,这与"Student"表(实际上是SQL Server视图)有关,但我可以在一秒钟内使用SQL从中选择所有行?
编写LINQ查询时,在需要数据之前,查询不会实际执行(请参阅延迟执行)。你的第一个db调用直到你在ri上foreach才发出。进步,这是一个单一的呼吁。
当你问ri的时候。复习。学生,你在要求更多的数据。所以你调用了数据库。因为您处于foreach循环中,所以您将对该循环中的每个项目的数据库进行一次调用。
这是一个"林n+1"问题。要解决此问题,您应该在一个查询中获取所有数据。你可以填充一个模型类并强烈键入视图,或者我认为你可以使用Linq.Include方法将Student数据包括在选择中
您可以通过启动SQL服务器探查器并执行跟踪来查看正在进行的调用
当您在foreach循环中请求学生数据时,您将对数据库进行大量查询:每次循环重复一次查询(如果感兴趣,请搜索N+1问题)。
使用include方法更改查询并将其列为列表(以避免延迟执行)应该可以解决您的问题:
var reviewitems = (
from ri in db.ReviewItems
where ri.Enrolment.Course.LearningArea.LearningAreaID == ID
&& ri.Review.ReviewSeries.StartDate < DateTime.Now
&& ri.Review.ReviewSeries.EndDate > DateTime.Now
&& ri.Progress < 2
select ri
).Include("Review.Student").ToList();
在上面的答案有力地指出这是一个n+1问题后,我在谷歌上搜索了一下。include方法对我不起作用(我的var类型是IQueryable,而不是ObjectQuery),但我确实在这里找到了解决方案:http://l2sprof.com/Learn/Alerts/SelectNPlusOne
通过在linq查询之前添加这段代码,页面加载速度非常快:
var loadoptions = new DataLoadOptions();
loadoptions.LoadWith<ReviewItem>(ri => ri.Review);
loadoptions.LoadWith<Review>(r => r.Student);
db.LoadOptions = loadoptions;
只有在sql server中创建一个存储过程(返回select语句和结果的所有列),然后用新的复杂类型更新您的实体框架,并将此新复杂类型与所选存储过程中函数导入的返回类型关联
结果将比以前快很多倍加入
这会更有帮助。。我想new procedure=>update EF=>new ComplexType(与select statemnet列的名称和类型相同)=>Add function import(右键单击procedure)=>link new complex type(在返回类型中)