当我打电话给Tolist时,转换需要很长时间,我该如何改进呢?

时间:2013-12-13 11:40:49

标签: 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(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()花了这么长时间呢?考虑到所有必需的数据已经存在..

任何见解?想法?

2 个答案:

答案 0 :(得分:1)

当调用最后一个ToList()时,它将为nonCompianceData中的所有项目执行此代码,这可能需要很长时间。

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()

我理解你在使用Linq返回的ToList()查询之前不应该使用IEnumerable<T>

除了它是关于优化你的Linq以生成更快的SQL。

答案 1 :(得分:0)

假设您正在使用Entity Framework(或其他ORM)...
那些coesData.Count(...导致加载UploadCOESDetailsCOESDetailsCOESDefects懒惰。

使用

context.COESDetails
    .Include(x => x.UploadCOESDetails)
    .Include(x => x.COESDetailsCOESDefects)

急切地加载它们。

或者在查询中挑选您需要的东西

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()
})