【发布时间】:2013-05-24 14:32:14
【问题描述】:
我正在运行一个 Linq 查询,它返回大约 25 条记录,每条记录有 10 个数字列。根据我的代码分析器,查询本身只需要几分之一秒 - 但对 .ToList() 的调用大约需要 3.5 秒。如前所述,从 SQL 返回的数据量是微不足道的,因此将其复制到 List 所花费的时间不应该是繁重的。
为什么.ToList() 需要这么长时间?又该如何改进?
编辑:感谢所有快速的答案,让我更清楚地说明:我完全知道查询是延迟加载的事实。我看到的现象是 SQL Server Profiler 和 ANTS Performance Profiler 都报告实际查询执行时间只有几分之一秒。
这是 ANTS 的屏幕截图:
请注意,调用方法耗时 4.3 秒,而实际 SQL 查询的耗时均不超过 0.05 秒。它可能是该方法中的其他代码,而不是 SQL?让我们看看 ANTS 是如何在这里分解代码配置文件的:
确凿证据:.ToList() 用时 3.36 秒,其中可能是 0.05 秒可归因于实际查询执行时间,剩下的 3.31 秒下落不明。
时间要去哪里?
编辑 2: 好的,你要求它,所以这是我的代码:
public static Expression<Func<Student, Chart>> GetStudentAssessmentQuestionResultByStudentIdNew(MyDataEntities db)
{
return s => new Chart
{
studentID = s.ID,
Lines =
db.StudentAssessmentAnswers
.Where(
saa =>
saa.StudentAssessment.BorrowedBook.StudentID == s.ID && saa.PointsAwarded != null &&
saa.Question.PointValue > 0 &&
(saa.Question.QuestionType == QuestionType.MultipleChoice ||
saa.Question.QuestionType == QuestionType.OpenEnded))
.GroupBy(
saa =>
new
{
saa.StudentAssessment.AssessmentYear,
saa.StudentAssessment.AssessmentMonth,
saa.Question.CommonCoreStandard
},
saa => saa)
.Select(x => new
{
x.Key.AssessmentYear,
x.Key.AssessmentMonth,
x.Key.CommonCoreStandard,
PercentagePointValue =
(float)(x.Sum(a => a.PointsAwarded) * 100) / (x.Sum(a => a.Question.PointValue))
})
.OrderByDescending(x => x.CommonCoreStandard)
.GroupBy(r1 => (byte)r1.CommonCoreStandard)
.Select(g => new ChartLine
{
ChartType = ((ChartType)g.Key),
//type = g.Key.ToString(),
type = g.Key,
Points = g.Select(grp => new ChartPoint
{
Year = grp.AssessmentYear.Value,
Month = grp.AssessmentMonth.Value,
yValue = grp.PercentagePointValue
})
})
};
}
这是由以下人员调用的:
var students =
db.ClassEnrollments
.Where(ce => ce.SchoolClass.HomeRoomTeacherID == teacherID)
.Select(s => s.Student);
var charts = CCProgressChart.GetStudentAssessmentQuestionResultByStudentIdNew(db);
var chartList = students.Select(charts).ToList();
这有帮助吗?
【问题讨论】:
-
也许你有这样的
db.Select(r => somefields).ToList().Where(i => filterHere);。然后您的查询将选择所有记录,您将在内存中过滤它们。将Where放在具体化之前,所以放在ToList之前。 -
您的查询是什么?
-
@Tim 提到的一个常见的微妙之处是,如果您过早将类型更改为
IEnumerable<T>,而不是IQueryable<T>- 例如:IEnumerable<Person> people = db.People; var qry = people.Where(x => x.Id == 12345).ToList();- 这会将整个表格拖到网络并在 LINQ-to-Objects 中执行Where,而不是通过 EF(它将在数据库中进行过滤)。所以:你能显示一些代码吗? -
@MarcGravell - 请查看我的编辑
-
@TimSchmelter - 请查看我的编辑
标签: c# linq linq-to-entities entity-framework-5