简体   繁体   English

汇总一个ObservableCollection的总数 <MyType> 带有Linq表达式

[英]Roll up totals of an ObservableCollection<MyType> with a Linq expression

I have a Silverlight delegate which gets an ObservableCollection in the EventArgs Result. 我有一个Silverlight委托,该委托在EventArgs结果中获取一个ObservableCollection。 The DTO myType has fields Order, StartDate, Status, PlannedAmount, ActualAmount, and few others. DTO myType具有字段Order,StartDate,Status,PlannedAmount,ActualAmount以及其他几个字段。 The query on the WCF service side gets several rows per Order, varying only by PlannedAmount and ActualAmount. WCF服务端的查询为每个订单获取几行,仅因PlannedAmount和ActualAmount有所不同。

Order # | StartDate | PlannedAmount| ActualAmount | Order Comments ....
Order A | March 15  |    20.00     |     0.00     | Comment 1 ...
Order A | March 15  |    30.00     |     0.00     | Comment 1 ...
Order A | March 15  |    10.00     |     0.00     | Comment 1 ...
Order A | March 15  |     0.00     |    30.00     | Comment 1 ...
Order B | March 25  |    10.00     |      0       | Comment 2 ...
Order B | March 25  |     0.00     |     5.00     | Comment 2 ...

I would like to show only one row per Order and sum all the PlannedAmount and ActualAmount values. 我只想为每个订单显示一行,并对所有PlannedAmount和ActualAmount值求和。 I prefer to change this in the presentation layer as I don't know what other consumers of the WCF Operation require. 我更喜欢在表示层中更改此设置,因为我不知道WCF操作的其他使用者需要什么。 So I want to roll it up to... 所以我想将其汇总到...

Order # | StartDate | PlannedAmount| ActualAmount | Order Comments ....
Order A | March 15  |    60.00     |    30.00     | Comment 1 ...
Order B | March 25  |    10.00     |    5.00      | Comment 2 ...

And then make this an ObservableCollection of the same type that I had before. 然后将其设为与我以前相同类型的ObservableCollection。

I have tried this but I cannot seem to get anything but the Key and the Sum values. 我已经尝试过了,但是除了Key和Sum值之外,我似乎什么也没得到。

    var Orders =
        from wo in OrdersPerOperation
        group wo by wo.OrderNo
        into g
        select new
        {
            OrderNo = g.Key,
            Planned = g.Sum(wo => wo.Planned),
            Actual = g.Sum(wo => wo.Actual),
            OrderComments = g.Select(wo => wo.Equipment),
            StartDate = g.Select(wo => wo.StartDate),
            Status = g.Select(wo => wo.Status),
            OrderType = g.Select(wo => wo.OrderType) //,...
        };

Edit 编辑
Getting just the key and two sums is straight-forward: 仅获得密钥和两个和就很简单:

var Orders =
        from wo in OrdersPerOperation
        group wo by wo.OrderNo
        into g
        select new
        {
            OrderNo = g.Key,
            Planned = g.Sum(wo => wo.Planned),
            Actual = g.Sum(wo => wo.Actual)
        }

The challenge is getting all of the other fields, which are repetitive to also show in the result. 挑战在于获取所有其他字段,这些字段必须重复显示在结果中。

EDIT 编辑
I made this guess that this might work like a self-referencing SQL query. 我猜想这可能像自引用SQL查询一样工作。 I believe I am on the right track with this, in that each element has data in the correct format. 我相信我在这方面是正确的,因为每个元素都具有正确格式的数据。 I still cannot set the results to the ItemsSource of the Silverlight grid, which I could bind, before all of this Linq confusion. 在所有这种Linq混乱之前,我仍然无法将结果设置为Silverlight网格的ItemsSource,可以绑定该项目。 The IDE warns me that FirstOrDefault is a possible NullReferenceException. IDE警告我,FirstOrDefault是可能的NullReferenceException。

var workOrders = from wo in workOrdersPerOperation
                group wo by wo.OrderNo
                into g
                select new
                {
                    OrderNo = g.Key,
                    Planned = g.Sum(wo => wo.Planned),
                    Actual = g.Sum(wo => wo.Actual),
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).Location,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).Equipment,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).StartDate,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).Status,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).OrderType,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).AccType,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).WorkCenter,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).Description,
                    g.FirstOrDefault(wo => wo.OrderNo == g.Key).Priority
                };

Can anyone get me past this step? 有人可以让我越过这一步吗? I still need to bind it to the control. 我仍然需要将其绑定到控件。

您需要g.SelectMany(wo => wo.Equipment)

尝试:

OrderComments = g.Select(wo => wo.Equipment).ToList()

I found that I could select into a collection of new instances of MyClass with initializers. 我发现我可以选择带有初始化程序的MyClass新实例的集合。

var orders = from wo in ordersPerOperation
    group wo by wo.OrderNo
    into g
    select new MyType()
    {
        OrderNo = g.Key,
        Planned = g.Sum(wo => wo.Planned),
        Actual = g.Sum(wo => wo.Actual),
        Location = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Location,
        Equipment = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Equipment,
        StartDate = g.FirstOrDefault(wo => wo.OrderNo == g.Key).StartDate,
        Status = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Status,
        OrderType = g.FirstOrDefault(wo => wo.OrderNo == g.Key).OrderType,
        AccType = g.FirstOrDefault(wo => wo.OrderNo == g.Key).AccType,
        WorkCenter = g.FirstOrDefault(wo => wo.OrderNo == g.Key).WorkCenter,
        Description = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Description,
        Priority = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Priority
    };

This is not an ObservableCollection, but it turns out that I don't need it be after all. 这不是ObservableCollection,但事实证明我根本不需要它。

I'm pretty sure that this 我很确定

Location = g.FirstOrDefault(wo => wo.OrderNo == g.Key).Location,

Will produce the same result as this 将产生与此相同的结果

Location = g.FirstOrDefault().Location,

Additionally, you only need to use FirstOrDefault if your collection might be empty. 此外,如果您的集合可能为空,则仅需要使用FirstOrDefault However, the group would not exist if there were no items in it. 但是,如果其中没有项目,则该组将不存在。 This allows you to simplify it down to this. 这使您可以简化它。

Location = g.First().Location,

You can make the final solution 您可以制定最终解决方案

var orders = from wo in ordersPerOperation
    group wo by wo.OrderNo
    into g
    select new MyType
    {
        OrderNo = g.Key,
        Planned = g.Sum(wo => wo.Planned),
        Actual = g.Sum(wo => wo.Actual),
        Location = g.First().Location,
        Equipment = g.First().Equipment,
        StartDate = g.First().StartDate,
        Status = g.First().Status,
        OrderType = g.First().OrderType,
        AccType = g.First().AccType,
        WorkCenter = g.First().WorkCenter,
        Description = g.First().Description,
        Priority = g.First().Priority
    };

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

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