linq分组结果需要很长时间

时间:2018-07-30 19:16:31

标签: c# linq .net-core

我有以下方法可以进行一些分组

private List<CatalogVehicle> GroupResult(IEnumerable<VehicleAndQuote> vehiclesAndQuotes)
    {
        var vehicles = vehiclesAndQuotes
            .GroupBy(vehicleAndQuote =>
                new
                {
                    vehicleAndQuote.Vehicle.VehicleMakeName,
                    vehicleAndQuote.Vehicle.VehicleModelTypeName,
                    vehicleAndQuote.Vehicle.VehicleEdition
                })
            .Select(a => new
            {
                vehicle = _mapper.Map<VehicleAndQuote, CatalogVehicle>(a.First()),
                plans = GetLeasingpPlansGroupedByYearlyMileages(a.ToList()) //<== this one is taking ages
            })
            .Select(a =>
            {
                a.vehicle.LeasingPlans = a.plans;
                return a.vehicle;
            });

        return vehicles.ToList();
    }

以及其中要调用的方法;

    private List<LeasingPlan> GetLeasingpPlansGroupedByYearlyMileages(IEnumerable<VehicleAndQuote> vehicleAndQuotes)
    {
        return vehicleAndQuotes.GroupBy(quote => quote.Quote.YearlyMileage)
            .Select(group => _mapper.Map<List<VehicleAndQuote>, LeasingPlan>(group.ToList()))
            .ToList();
    }

最后一种方法花费很长时间。 IEnumerable<VehicleAndQuote> vehiclesAndQuotes大约有30.000条记录。 我看不到任何性能提升者吗?

2 个答案:

答案 0 :(得分:2)

我正在尝试将您的查询转换为对数据库更友好的版本。

var vehicles = vehiclesAndQuotes
    .GroupBy(vehicleAndQuote =>
                new {
                    vehicleAndQuote.Vehicle.VehicleMakeName,
                    vehicleAndQuote.Vehicle.VehicleModelTypeName,
                    vehicleAndQuote.Vehicle.VehicleEdition
                })
            .Select(a => new {
                // DB friendly
                vehicle = a.First(),
                plans = a.GroupBy(quote => quote.Quote.YearlyMileage)
            })
            .AsEnumerable() // May o may not be needed / passing to LINQ to Objects
            .Select(a => {
                var vehicle = _mapper.Map<VehicleAndQuote, CatalogVehicle>(a.vehicle);
                var plans = a.plans.Select(group => _mapper.Map<IEnumerable<VehicleAndQuote>, LeasingPlan>(group));
                vehicle.LeasingPlans = plans;
                return vehicle;
            });

return vehicles.ToList(); // This should be avoided, specially if you are processing a large collection.

这样,您就可以在数据库端进行双重分组了。另外,直到最后我都没有实现整个系列。

希望这会有所帮助!

答案 1 :(得分:1)

SQL Profiler中检查生成的查询。您的查询正在对(N+1 problem)vehicle中的每个记录plans进行选择。如果您使用的是Entity Framework 2.0,则应该知道它在本地运行GroupBy,并且像SELECT *一样从数据库中提取所有数据到内存中,然后将它们分组在内存中。在每个实体的多个查询中拆分查询。请勿在您的LINQ LINQ函数中使用First()之类的Select函数,因为它会导致N+1 SQL Issue。将EF版本升级到2.1或更高版本,以避免出现Local GroupBy问题。