Добавить вложенные значения из списков вложенных классов в Linq

Прошу прощения за объем кода, но мне сложно по-настоящему объяснить структуру каждого класса, поэтому я надеюсь, что это нормально, что я включил так много. Итак, я изучаю более сложные запросы с помощью Linq на C #. Большинство из них включают запросы к многочисленным полям из множества вложенных объектов.

Моя проблема - выяснить, как получить нужную мне информацию. Например, тот, на котором я застрял сейчас, который побудил меня сделать это, показан ниже. Я должен запросить идентификатор заказа, имя / фамилию клиента и общую сумму для всех заказов с размещенным статусом. Существует множество других сгенерированных объектов, но у них нет статуса размещения, поэтому я не включил их.

Текущий запрос, показанный ниже, возвращает Роджера 4 раза и Мэри 5 раз. Это правильно, потому что они закодированы, потому что в них 4 адда для Роджера и 5 для Мэри. Однако я не получаю фамилию и не имею ни малейшего представления о том, как суммировать все размещенные заказы.

При попытке использовать какую-либо функцию .Sum или .Count он их не распознает. Я знаю, что я, вероятно, неправильно формирую данные с помощью моих избранных новых операторов. Я ищу некоторое представление о том, как минимизировать объем выводимых данных, а также о том, в каком направлении двигаться, чтобы выполнить сложение итогов.

 class Customer
        {
            public int CustomerID { get; set; }
            public String FirstName { get; set; }
            public String LastName { get; set; }
            public String Email { get; set; }

            public Customer(int id, String fName, String lName, String email)
            {
                CustomerID = id;
                FirstName = fName;
                LastName = lName;
                Email = email;
            }
        }
    }

        class Order
    {
        public int OrderID { get; set; }
        public DateTime OrderDate { get; set; }
        public String ShippingMethod { get; set; }
        public String OrderStatus { get; set; }
        public Customer OrderedBy { get; set; }
        public List<Product> OrderItems { get; set; }

        public Order(int ordId, DateTime ordDate, String shipMethod, String ordStatus, Customer cust)
        {
            OrderID = ordId;
            OrderDate = ordDate;
            ShippingMethod = shipMethod;
            OrderStatus = ordStatus;
            OrderedBy = cust;
            OrderItems = new List<Product>();
        }

        public void addProduct(Product prod)
        {
            OrderItems.Add(prod);
        }
        public double calcOrderTotal()
        {

            var itemVar = OrderItems.Sum(i => i.calcProductTotal());

            return itemVar;
        }
        public double calcShipping()
        {
            double total = 0;
            return total;
        }

    }
}

    class Product
    {
        public int ProdID { get; set; }
        public String Name { get; set; }
        public double Price { get; set; }
        public String Image { get; set; }
        public String Desc { get; set; }
        public int QtyOrdered { get; set; }
        public double Weight { get; set; }

        public Product(int id, string name, double price)
        {
            ProdID = id;
            Name = name;
            Price = price;
        }
        public Product(int id, string name, double price, string image, string desc)
            : this(id, name, price)
        {
            Image = image;
            Desc = desc;
        }
        public Product(int id, string name, double price, int qty, double weight) : this(id, name, price)
        {
            QtyOrdered = qty;
            Weight = weight;
        }
        public double calcProductTotal()
        {
            return Price * QtyOrdered;
        }
    }
}

   class Program
{
    static void Main(string[] args)
    {   //http://msdn.microsoft.com/en-us/vcsharp/aa336746
        List<Order> orders2 = setupData2();

private static List<Order> setupData2()
        {
    List<Order> orders = new List<Order>();
            Customer c1 = new Customer(14, "Mary", "Smith", "[email protected]");
            Customer c2 = new Customer(25, "Andy", "Johnson", "[email protected]");
            Customer c3 = new Customer(42, "Tim", "Clark", "[email protected]");
            Customer c4 = new Customer(125, "Roger", "Wilson", "[email protected]");

    Order ord4 = new Order(48, DateTime.Now.Subtract(new TimeSpan(4, 1, 1, 1, 1)), "Ground", "Placed", c4);
            ord4.addProduct(new Product(129, "Do It Yourself Tornado Kit", 225.50, 4, 85.5));
            ord4.addProduct(new Product(421, "Catcus Costume", 48.70, 2, 18.85));
            ord4.addProduct(new Product(400, "Anvil", 338.70, 1, 384.25));
            ord4.addProduct(new Product(455, "Jet Propelled Unicycle", 556.40, 4, 328.35));
            orders.Add(ord4);

            Order ord5 = new Order(55, DateTime.Now.Subtract(new TimeSpan(1, 1, 1, 1, 1)), "Ground", "Placed", c1);
            ord5.addProduct(new Product(124, "Earth Quake Pills", 145.50, 3, 2.25));
            ord5.addProduct(new Product(129, "Do It Yourself Tornado Kit", 225.50, 1, 85.5));
            ord5.addProduct(new Product(327, "Giant Mouse Trap", 88.70, 4, 26.50));
            ord5.addProduct(new Product(400, "Anvil", 338.70, 2, 384.25));
            ord5.addProduct(new Product(425, "Iron Bird Seed", 27.70, 1, 5.85));
            orders.Add(ord5); }

                                var orders = (from o in orders2
                      from p in o.OrderItems
                      where o.OrderStatus == "Placed"
                      orderby o.OrderDate
                      let total = p.Price * p.QtyOrdered
                      select new { o.OrderID, o.OrderedBy.FirstName, o.OrderedBy.LastName, Total = total });
        double totalOrders = 0;
        foreach (var x in orders)
        {            
            Console.WriteLine("Order Id: " + x.OrderID + " Ordered by: " + x.FirstName + " " + x.LastName);
            totalOrders+= x.Total;
        }
        Console.WriteLine("Price for all Orders: " + totalOrders);
}

Возможное групповое решение, но сейчас нельзя втягивать имена.

            var ordersTotal = from o in orders2
                          from p in o.OrderItems
                          where o.OrderStatus == "Placed"
                          orderby o.OrderDate
                          group p by o.OrderID into g
                          select new { OrderId = g.Key, Price = g.Sum(p => p.Price * p.QtyOrdered) };

person The_fatness    schedule 15.03.2017    source источник
comment
Откуда вы получаете заказы2?   -  person h-rai    schedule 15.03.2017
comment
Во-первых, у вас есть два объекта с именем orders (плохое кодирование), во-вторых, вы не получаете LastName, потому что ваш анонимный тип имеет o.OrderedBy.LastName, когда вы помещаете элементы в этот тип, он уже упорядочен теми командами, которые были до orderby o.OrderDate   -  person Edward    schedule 15.03.2017
comment
@ nick-s Извините, это моя инициализация коллекций заказов. Теперь код должен обновляться правильно. Он просто создает список со всеми заказами в нем, который является методом SetupData2, и я вызываю этот список заказов2.   -  person The_fatness    schedule 15.03.2017
comment
Не могу найти метод setupData2 () !?   -  person h-rai    schedule 15.03.2017
comment
@ nick-s Проверьте сейчас, форматирование должно быть правильным.   -  person The_fatness    schedule 15.03.2017
comment
@Edward, что запрещено. Говорит, что «Порядок» не содержит определения для фамилии.   -  person The_fatness    schedule 15.03.2017
comment
@Edward На самом деле нет, этого не требуется. Имена свойств в анонимных типах являются производными от свойства OrderedBy.   -  person h-rai    schedule 15.03.2017
comment
Чтобы получить ваши подсчеты (индексацию), ваше решение можно найти здесь index показывает, как это сделать с помощью обычного linq и лямбда-выражения.   -  person Edward    schedule 15.03.2017
comment
Не совсем понятно, КАКАЯ сумма вам действительно нужна. Это может быть общее количество заказов или общее количество продуктов, заказанных во всех заказах вместе, или это может быть сумма стоимости всех продуктов во всех заказах.   -  person h-rai    schedule 15.03.2017


Ответы (2)


Попробуйте этот код.

            var orders = (from o in orders2
                          where o.OrderStatus == "Placed"
                          orderby o.OrderDate
                          select new { o.OrderedBy.FirstName, o.OrderedBy.LastName }).Distinct();

            foreach (var x in orders)
            {
                Console.WriteLine(x.FirstName + " " + x.LastName);
            }

            Console.WriteLine(orders2.Sum(order => order.OrderItems.Select(item =>(double)(item.QtyOrdered * item.Price)).Sum()));
person h-rai    schedule 15.03.2017
comment
Лучший способ для этого в C # - Console.WriteLine("{0} {1}", x.FirstName, x.LastName); - person Edward; 15.03.2017
comment
Хорошо, я сделал это, и это работает. Это немного некрасиво, но с вашими комментариями и комментариями Эдвардса я сузил проблему до печати каждого .addProduct. Я полагаю, что это часть цикла foreach. Что мне нужно сделать сейчас, так это расшифровать, как заставить его печатать каждую строку один раз, а затем выводить итог внизу. Я обновлю код тем, что у меня есть сейчас. - person The_fatness; 15.03.2017
comment
Вы имеете в виду одну строку для каждого имени? - person h-rai; 15.03.2017
comment
@ nick-s Я пробовал реализовать Distinct (), но он все еще выводит его несколько раз. Что касается вашего другого комментария, обновленный код теперь правильно добавляет итоги, хотя, вероятно, это плохой способ сделать это. - person The_fatness; 15.03.2017
comment
Это потому, что ваш select new код был изменен на Total, который будет отличаться для каждой строки, даже если у нее один и тот же Customer. - person h-rai; 15.03.2017
comment
@The_fatness правильным способом будет groupby then sum, также groupby уменьшит набор результатов для каждого человека, как вы хотите. - person Edward; 15.03.2017
comment
@ nick-s Ваш обновленный код выводит каждое значение построчно, делая вычисления, я не уверен, откуда берутся эти значения. Цена * кол-во не совпадает ни в одной строке. Эдвард: Сейчас я пытаюсь использовать группу. - person The_fatness; 15.03.2017
comment
@Edward Я добавил группу с суммой в конец OP. Не могу понять, как включить имена сейчас. - person The_fatness; 15.03.2017
comment
@ nick-s Большое спасибо - person The_fatness; 15.03.2017

Взгляните на эту .NET-скрипку вашего кода

https://dotnetfiddle.net/91yYMF

Он показывает, как можно рассчитать сумму. Вам еще что-нибудь нужно сделать?

person Daveo    schedule 15.03.2017
comment
не уверен, что вы говорите, этот код я опубликовал. Ничего не меняется, и он по-прежнему не выводит правильную информацию. - person The_fatness; 15.03.2017
comment
@The_fatness Я просто показывал альтернативный способ сделать это - см. Раздел Another way to do it, который я просил уточнить, правильная информация? Так как я не уверен, что вы пытаетесь сделать - person Daveo; 16.03.2017