简体   繁体   English

在linq查询中计算总数

[英]Calculating totals in linq query

I have a Model called JobReport which looks like this (simplified) 我有一个名为JobReport的模型,看起来像这样(简化)

public class JobReport
{
    public JobReport()   
    {
        WorkOrders = new List<WorkOrder>();
    }
    public int JobID { get; set; }
    public decimal WorkOrderTotal {get; set; }
    public List<WorkOrder> WorkOrders{ get; set; }
}

public class WorkOrder
{
    public WorkOrder()   
    {
        Total = 0;
    }
    public string Trade { get; set; }
    public int WorkOrderID { get; set; }
    public decimal? Total { get; set; }
}

I now have a Linq query which gets me all the Jobs that have WorkOrders that have a trade which is in a passed array thanks to Linq Query where related entity contains value from array : 现在,我有了一个Linq查询,这要感谢所有具有WorkOrders且其交易在传递数组中的工作的Job,这要归功于Linq Query,其中相关实体包含array的值

jobs = jobs
.Where(x => x.WorkOrders.Any(y => trades.Contains(y.Trade)));

How do I now get the WorkOrderTotal, which is the sum of the Total in the workorders that meet the predicate of the above query? 现在如何获取WorkOrderTotal,即满足上述查询谓词的工单中的Total的总和? I can't see how to add .Sum() anywhere? 我看不到如何在任何地方添加.Sum()?

EDIT 编辑

Just to confirm, each job needs the sum of it's workorders that are in the given trades. 只是为了确认,每个工作都需要给定行业中工作单的总和。

Try something like this: 尝试这样的事情:

    IEnumerable<decimal> workOrderTotals = jobs
        .Where(x => x.WorkOrders.Any(y => trades.Contains(y.Trade)))
        .Select( j => j.WorkOrders.Sum(wo => wo.Total ?? 0)); 

And here's a test case : 这是一个测试用例:

  var jobs = new List<JobReport>();
        jobs.Add(new JobReport{ WorkOrders = new List<WorkOrder>{ new WorkOrder{ Total = 10} }});
        jobs.Add(new JobReport { WorkOrders = new List<WorkOrder> { new WorkOrder { Total = 10 }, new WorkOrder { Total = 10 } } });

The result is an enumerable containing 2 values 10 , 20 结果是包含2个值10,20的可枚举

Considering this as the test data 将此视为测试数据

        JobReport job1 = new JobReport();
        job1.JobID = 1;
        job1.WorkOrders.Add(new WorkOrder() { WorkOrderID = 2, Trade = "trade1", Total = 10});
        job1.WorkOrders.Add(new WorkOrder() { WorkOrderID = 3, Trade = "trade2", Total = 20 });
        job1.WorkOrders.Add(new WorkOrder() { WorkOrderID = 4, Trade = "trade1", Total = 25 });

        JobReport job2 = new JobReport();
        job2.JobID = 2;
        job2.WorkOrders.Add(new WorkOrder() { WorkOrderID = 1, Trade = "trade1", Total = 10 });
        job2.WorkOrders.Add(new WorkOrder() { WorkOrderID = 5, Trade = "trade2", Total = 20 });
        job2.WorkOrders.Add(new WorkOrder() { WorkOrderID = 6, Trade = "trade2", Total = 30 });
        job2.WorkOrders.Add(new WorkOrder() { WorkOrderID = 7, Trade = "trade3", Total = 10 });

        List<JobReport> jobs = new List<JobReport>();
        jobs.Add(job1);
        jobs.Add(job2);

You could do something like this. 你可以做这样的事情。

var groupedJobs = jobs.GroupBy(a => a.JobID)
            .Select(b => new { JobId = b.Key, WorkOrdersByTrade = b.Select(c => c.WorkOrders.GroupBy(d => d.Trade)
            .Select(g => new { Trade = g.Key, tradeSum = g.Sum(s => s.Total) })) });

Further by defining the following classes 通过定义以下类进一步

    public class TradeTotal
    {
        public string Trade { get; set; }
        public decimal? Total { get; set; }
    }

    public class JobTrade
    {
        public int JobId { get; set; }
        public List<TradeTotal> TradeTotals { get; set; }
    }

You can get the results in the format that you wanted 您可以以所需的格式获得结果

var JobTradeList = groupedJobs.Select(x => new JobTrade() { JobId = x.JobId, TradeTotals = x.WorkOrdersByTrade.SelectMany(s => s.Select(v => new TradeTotal() { Total = v.tradeSum, Trade = v.Trade })).ToList() }).ToList();

Code may be not 100% clean; 代码可能不是100%干净的; but I think this is what you are after. 但是我想这就是你所追求的。

在此处输入图片说明

Perhaps a slightly easier solution to those already posted would be to add a property to your JobReport called WorkOrderValue: 对于已经发布的解决方案,也许稍微容易一点的解决方案是在JobReport中添加一个名为WorkOrderValue的属性:

public decimal? WorkOrdersValue { get; set; }

Now you can query on the jobs that meet your criteria: 现在,您可以查询符合条件的职位:

jobs = jobs
    .Where(x => x.WorkOrders
        .Any(y => trades.Contains(y.Trade.ToLower())))
        .ToList();

And separately calculate the total for each job: 并分别计算每个作业的总数:

foreach (var job in jobs)
{
    job.WorkOrdersValue = job.WorkOrders.Where
        (y => trades.Contains(y.Trade.ToLower())).Sum(wo => wo.Total);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM