C# 当我调用Tolist时,转换需要很长时间,我如何改进这一点?
我有下面的代码,最后一个toList语句花费了很长时间。有什么办法可以改进吗C# 当我调用Tolist时,转换需要很长时间,我如何改进这一点?,c#,.net,linq,asp.net-mvc-4,C#,.net,Linq,Asp.net Mvc 4,我有下面的代码,最后一个toList语句花费了很长时间。有什么办法可以改进吗 //This statement takes less than 1 second var inspectorData = context.COESDetails.Where(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth.Contains(crit
//This statement takes less than 1 second
var inspectorData = context.COESDetails.Where(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth.Contains(criteria.AuditYear)).Select(x => x.Inspector).Where(y => y.Id != 0).Distinct().OrderBy(x => x.Firstname).ToList();
//This statement takes less than 1 second
var coesData = context.COESDetails.Where(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth.Contains(criteria.AuditYear)).ToList();
//this takes less than 1 second
var nonComplianceData = inspectorData
.Select(ud =>
new NonComplianceData
{
InspectorId = ud.Id,
InspectorName = ud.Firstname + " " + ud.Surname,
FullYearData = Constants.Months.Select(month => new MonthData
{
Month = month,
TotalAuditsCompleted = coesData.Count(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth == (month + " " + criteria.AuditYear) && x.InspectorId == ud.Id && x.AuditType != (int)AuditType.NotSelected),
TotalNoDefects = coesData.Count(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth == (month + " " + criteria.AuditYear) && x.InspectorId == ud.Id && x.AuditType != (int)AuditType.NotSelected && x.COESDetailsCOESDefects.Any())
}).ToList()
});
// this statement takes about 14 seconds
return nonComplianceData.ToList();
我想,当我在前两条语句中调用toList()时,我认为查询正在执行,我有了所需的数据。那么,为什么最后一次收费要花这么长时间呢?考虑到所有要求的数据已经存在
有什么见解吗?想法?当调用最后一个ToList()
时,它将对非计划数据中的所有项目执行此代码,这可能需要很长时间
FullYearData = Constants.Months.Select(month => new MonthData
{
Month = month,
TotalAuditsCompleted = coesData.Count(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth == (month + " " + criteria.AuditYear) && x.InspectorId == ud.Id && x.AuditType != (int)AuditType.NotSelected),
TotalNoDefects = coesData.Count(x => x.UploadCOESDetails.AuditZoneId == criteria.AuditZoneId && x.UploadCOESDetails.AuditMonth == (month + " " + criteria.AuditYear) && x.InspectorId == ud.Id && x.AuditType != (int)AuditType.NotSelected && x.COESDetailsCOESDefects.Any())
}).ToList()
据我所知,在真正需要之前,您不应该使用ToList()
,在此之前,请使用Linq返回的IEnumerable
查询
除此之外,它还涉及优化Linq以生成更快的SQL。假设您使用的是实体框架(或其他ORM)…
那些coesData.Count(…
导致延迟加载UploadCOESDetails
和coesdetails缺陷
使用
急切地装载它们
或者在查询中选择所需的内容
var coesData = context.CoesData.Select(x => new
{
x.Id,
x.UploadCOESDetails.AuditZoneId,
x.UploadCOESDetails.AuditMonth,
x.InspectorId,
x.AuditType,
/* etc. */
DefectCount = x.COESDetailsCOESDefects.Count(),
/* or this if it works... */
HasDefects = x.COESDetailsCOESDefects.Any()
})
Select
除了创建一个查询外,什么也不做,ToList
执行它并从结果中创建一个集合。与上面的Where
相同。您应该阅读。如果运行该查询需要14秒,那么您需要更改查询或更改使用结果的方式。为什么必须返回列表
而不是IEnumerable
(这将允许更好的延迟评估)?您还可以将不符合要求的数据。FullYearData
作为IEnumerable
(假设它是只读的)哪一个会做类似的事情。有什么是延迟加载的吗?我注意到最后一个linq语句buildingnoncompliance data
访问了从上面的上下文返回的实体的很多属性。context
Entity Framework DbContext吗?谢谢大家,是的,这与两个计数有关..延迟加载。我只是假设,因为我如果在coesDetails中执行ToList,所有关联的实体都会被急切地加载……我错了……感谢所有的帮助,ToList
不会在延迟的迭代中导致性能问题。如果您要正常迭代,它的成本是相同的。ToList
只需提前加载成本,而在迭代中,您可能实现,也可能无法实现我怀疑内部FullYearData
属性的构造实际上是成本,要么是由于对大型集合的嵌套迭代,要么是由于对实体的延迟加载属性。这实际上取决于是否要访问整个枚举。与所有内容一样,这完全取决于思考如果ToList()
不是为创建coesData而调用的
它可能会导致生成不合规数据的耗时查询中使用的属性不会被延迟加载。相反,整个查询可以在一个SQL查询中执行。哦,我明白了。您的答案比不调用ToList
更重要,如果人们只做一部分ial迭代成本不高。谢谢。这将整个操作缩短到了2秒。我完全忘记了UploadCOESDetails和CoesDetails缺陷是通过延迟加载使用的。非常棒的工作,非常感谢。不过,只有一件事..要急切地加载实体,它的.Include(“UploadCOESDetails”).Include(“coesdetailscoesfects”)……我知道你的意思……再次感谢……做出了如此大的改变
var coesData = context.CoesData.Select(x => new
{
x.Id,
x.UploadCOESDetails.AuditZoneId,
x.UploadCOESDetails.AuditMonth,
x.InspectorId,
x.AuditType,
/* etc. */
DefectCount = x.COESDetailsCOESDefects.Count(),
/* or this if it works... */
HasDefects = x.COESDetailsCOESDefects.Any()
})