linq对象集合

时间:2017-10-12 09:27:51

标签: c# linq collections

我有这段代码可行:

        var mealsAndSchoolsPerformance = new List<MealsAndSchoolPerformanceUI>();

        foreach (SchoolModel sc in schoolData.Where(s => s.IsHidden == false))
        {
            var mealAndSchoolP = new MealsAndSchoolPerformanceUI
            {
                Id = sc.Id,
                SchoolName = sc.SchoolName,
                Week = DateExtensions.GetIso8601WeekOfYear(startDate, true),
                TotalFoodSpent = foodSpend.ContainsKey(sc.Id) ? foodSpend[sc.Id] : 0,
                TotalHours = totalHours.ContainsKey(sc.Id) ? totalHours[sc.Id]: 0,
                MealsKs1 = meals.Where(m => m.SchoolId == sc.Id).Where(m => m.InvoiceMealType == InvoiceMealType.KeyStage1).Sum(s => s.MealNo), 
                MealsKs2 = meals.Where(m => m.SchoolId == sc.Id).Where(m => m.InvoiceMealType == InvoiceMealType.KeyStage2).Sum(s => s.MealNo), 
                MealsNursery = meals.Where(m => m.SchoolId == sc.Id).Where(m => m.InvoiceMealType == InvoiceMealType.Nursery).Sum(s => s.MealNo), 
                MealsStaff = meals.Where(m => m.SchoolId == sc.Id).Where(m => m.InvoiceMealType == InvoiceMealType.Adult).Sum(s => s.MealNo),
                MealsSenior = meals.Where(m => m.SchoolId == sc.Id).Where(m => m.InvoiceMealType == InvoiceMealType.Senior).Sum(s => s.MealNo),
                TotalSales = meals.Where(m => m.SchoolId == sc.Id).Sum(m => m.TotalPrice),
                TotalInvoicePrice = meals.Where(m => m.SchoolId == sc.Id).Sum(m => m.TotalInvoicePrice),
                Region = sc.SchoolLead?.AddressRegion ?? " ",
                SchoolGroup = sc.SchoolGroups.FirstOrDefault()?.GroupName ?? "",
                Manager = sc.ManagerUser?.FullName ?? "",
                ServiceStarted = sc.ServiceStarted,
                RollNoNursery = sc.RollNoNursery ?? 0,
                RollNoSchool = sc.RollNoSchool ?? 0,
                ServingDays = MealBL.MealServingDays(sc.Id, startDate, startDate.AddDays(6))
            };
            mealsAndSchoolsPerformance.Add(mealAndSchoolP);
        }

问题是:有没有办法同时初始化列表和每个对象以提高性能?

之类的东西

var mealsAndSchoolsPerformance = new List();

2 个答案:

答案 0 :(得分:0)

There is no way to initialize a list and multiple objects "at the same time". Linq can make your code shorter but under the hood it will foreach over the data just the same.

But you can improve performance: you're executing the meals.Where(m => m.SchoolId == sc.Id) part multiple times, while you could do this once and hang on to the result:

foreach (SchoolModel sc in schoolData.Where(s => s.IsHidden == false))
{
    var schoolMeals = meals.Where(m => m.SchoolId == sc.Id).ToArray();
    ...
    TotalSales = schoolMeals.Sum(m => m.TotalPrice),
    TotalInvoicePrice = schoolMeals.Sum(m => m.TotalInvoicePrice),

Furthermore you're running similar InvoiceMealType queries over the same data, where you could do this in a single pass:

foreach (SchoolModel sc in schoolData.Where(s => s.IsHidden == false))
{
    var schoolMeals = meals.Where(m => m.SchoolId == sc.Id);
    var byInvoiceMealType = schoolMeals.ToLookup(m => m.InvoiceMealType);
    ...
    MealsKs1 = byInvoiceMealType[InvoiceMealType.KeyStage1].Sum(s => s.MealNo),

Perhaps this was not the answer you were hoping to get - and how much performance is gained depends on the source and amount of data.

答案 1 :(得分:0)

您可以使用PLINQ中的Task Parallel Library一次初始化多个线程上的对象,从而提高多核处理器的性能。这假设对象初始化中使用的数据源(例如foodSpendmeals)对于读取和枚举是线程安全的(我不知道是否在不知道这些对象的类型的情况下,但{ {1}},Dictionary<T>和数组使用这种方式是安全的,对于其他类型,您必须自己检查线程安全性。)

List<T>

此性能改进不排除@ C.Evenhuis建议的那些,所以为了获得最佳性能,您应该将它们组合在一起。