2

After some hours of trying and researching I'm still stuck with the following problem.

I have a list of customers, each customer has a list of orders. I now want to sort the list of customers by their highest order number. Another aspect is that not every customer has an order, so for sorting i want to replace the missing order number with an “-“ sign.

My first approach won’t work because it can’t compare the object, but it explains the problem quite well.

customers.OrderBy(m => m.Orders == null ? "-" : m.Orders.LastOrDefault().OrderNumber.ToString());

After reading the link below I ended up with this code, but that is not working either.

how do I sort a collection with child property?

customers.OrderBy(c => c.Orders.OrderBy(o => o == null ? "-" : o.OrderNumber.ToString()).Select(o => o == null ? "-" : o.OrderNumber.ToString()).ToList();

Can someone tell me how I can do this best?

Best Regards

Edit:

Here are the entities (not full entity) I'm trying to sort. I'm working with entity framework and I've already read out the customers as an IQueryable and now I need to sort this.

Customer

public class Customer
{
    public int ID { get; set; }
    public virtual List<Order> Orders { get; set; }
}

Order

public class Order {
    public int ID { get; set; }
    public int OrderNumber { get; set; }
    public virtual Customer Customer { get; set; }
}

Now the customer does not necessarily have a list of orders associated. Meaning a customer can have 0,1 or n orders assigned to him, that's what I meant with null.

Community
  • 1
  • 1
vitalragaz
  • 308
  • 1
  • 10
  • please add input & output for better understand – reza.cse08 May 26 '16 at 10:09
  • From your comments for the current answer looks like you are seeking for LINQ to Entities query. If that's true, please update the post and tags accordingly. This is because LINQ to Entities supports limited set of constructs, and also neither `m.Orders` in your first approach nor `o` in your second approach can be `null`. – Ivan Stoev May 26 '16 at 10:42
  • I'll update my question shortly. – vitalragaz May 26 '16 at 10:55
  • Btw, are you sure order by number converted to string will produce a correct ordering? I don't think so, for instance "11" will be before "2". And by "-" I guess you want customers w/o orders to be first in the order. – Ivan Stoev May 26 '16 at 11:30
  • You are absolutley right string-compare is not the correct approach – vitalragaz May 26 '16 at 11:50

2 Answers2

2

I now want to sort the list of customers by their highest order number.

Then the following should do the trick:

var result = customers.OrderBy(c => c.Orders.Max(o => (int?)o.OrderNumber));

The int? cast is needed to let Max function return null for customers w/o orders. This normally would put them at the beginning of the sort order.

In case you want to put customers w/o orders at the end, the simplest would be to use int.MaxValue (assuming you have no OrderNumber == int.MaxValue):

var result = customers.OrderBy(c => c.Orders.Max(o => (int?)o.OrderNumber) ?? int.MaxValue);
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
0

You could first remove the customers with no Orders and then add them back with Concat()

customers
  .Where(c => c.Orders.Count() != 0)
  .OrderBy(c => c.Orders.OrderBy(o => o.OrderNumber).Select(o => o.OrderNumber).FirstOrDefault())
  .Concat(customers.Where(c => c.Orders.Count() == 0))
  .ToList();

Let me know if that works for your use-case.

So Long

Michael Lopez
  • 153
  • 1
  • 9
  • Don't work :( -> Cannot compare elements of type 'System.Collections.Generic.List`1[[Lib.Entitys.Order, Lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'. Only primitive types, enumeration types and entity types are supported. – vitalragaz May 26 '16 at 10:26
  • Edited my answer: FirstOrDefault was missing, it tried to order with the list not with the OrderNumber that should have caused your error – Michael Lopez May 26 '16 at 10:30
  • Still the same issue. I will add an example fiddle in minutes – vitalragaz May 26 '16 at 10:32
  • I think the issue is related to the comparison in the Where Clauses. Try and use the updated Code with o.Count == 0 not o == null – Michael Lopez May 26 '16 at 10:40
  • That seams to work. I'm now only running into an issue with concate and skip. After your query, without .ToList() at the end for DB performance, I would like to add a paging function, via Skip and Take, but it is throwing an error cause I'm getting back a IQueryable instead of the expected IOrderedQueryable. Has anyone an input on that? – vitalragaz May 26 '16 at 11:38