2

How do you sort a class based on the property of its child class which is a collection? I'm doing a product and bid project where some products won't have bids and some will have bids. Here's what I've been trying but the problem is it gives me an "At least one object must implement IComparable" exception.

EDIT

The goal is to sort the products based on which of them has the highest or lowest bid.

Ascending Sort Example

|---------------------|------------------|
|      Product        |  Most Recent Bid |
|---------------------|------------------|
|          1          |         $100     |
|---------------------|------------------|
|---------------------|------------------|
|          2          |         $150     |
|---------------------|------------------|
|---------------------|------------------|
|          3          |         $175     |
|---------------------|------------------|

My Solution

productList = Sort == true ?
productList.OrderBy(x => x.Bids.OrderByDescending(y => y.BidAmount)) :
productList.OrderBy(x => x.Bids.OrderBy(y => y.BidAmount));

Product Class

public class Product
    {
        [Key]
        public Guid ProductId { get; set; }
        [MaxLength(30)]
        public string ProductName { get; set; }
        [MaxLength(200)]
        [Required]
        public string ProductDescription { get; set; }
        [Required]
        public string ImgUrl { get; set; }
        [Required]
        public DateTime ExpiryDate { get; set; }

        [Required]
        public DateTime UploadDate { get; set; }
        public ICollection<Bid> Bids { get; set; }
    }

Bid Class

public class Bid
    {
        [Key]
        public Guid BidId { get; set; }
        [Required]
        public decimal BidAmount { get; set; }
        [Required]
        public DateTime BidDate { get; set; }
        [Required]
        [ForeignKey("Product")]
        public Guid ProductId { get; set; }
        public Product Product { get; set; }
        [Required]
        [ForeignKey("User")]
        public Guid UserId { get; set; }
        public User User { get; set; }
    }

I have tried using solutions from both this and this but none cover the collection property use case.

  • Does this answer your question? [At least one object must implement IComparable calling OrderBy()](https://stackoverflow.com/questions/29465104/at-least-one-object-must-implement-icomparable-calling-orderby) – Trevor Oct 27 '20 at 12:56
  • Is there a specific reason you're using `ICollection` versus `IEnumerable` or it's derivatives? – Hazel へいぜる Oct 27 '20 at 12:58
  • @Çöđěxěŕ, unfortunately, it doesn't because it doesn't show access to to a parameter within the child list. – jeremiah valero Oct 27 '20 at 13:08
  • @Taco No particular reason, although I have tried using the different ones it still ends up throwing the same error. – jeremiah valero Oct 27 '20 at 13:08
  • Your `Bid`s can be ordered by BidAmount but your `Product`s can not. I mean, the compiler does not know how do you want to compare a `Product`. By the ProductId, Name, length of the URL maybe? :) You have to implement a comparer and specify your requirements. *Edit: How do you want to sort your Products? Number of bids? Highest bid? Sum of bid? – uTeisT Oct 27 '20 at 13:31
  • It is unclear precisely how you want your products to be ordered. In plain English, please explain the sorting order of the products. Are you trying to sort by how many bids a product has? The highest bid a product has? Average bid price? When the most recent bid was placed? ... – Flater Oct 27 '20 at 13:38
  • I've added an edit to the question. Essentially the goal is to sort it based on the highest bid a product has. Each product will have multiple bids, therefore the highest bid price will be used to sort for each product. – jeremiah valero Oct 27 '20 at 13:46
  • Well, then the first link you share *does* apply. – Gert Arnold Oct 27 '20 at 13:50

1 Answers1

0

Ordering the Bids based on amount is not throwing that error. The problem is x.Bids.OrderBy(...) returns a list of Bids so you are trying to order the Products based on a list of Bids. Since there is no way to compare a generic list to another, you need to be more specific.

If you want to order the products based on the number of bids you could use this

productList.OrderBy(x => x.Bids.Count());

Or if you want to order the products based on the total amount of the bids you could use this

productList.OrderBy(x => x.Bids.Sum(b => b.BidAmount));
schwechel
  • 305
  • 3
  • 10
  • 1
    I get what you are saying, I updated my answer to reflect that the ordering of the Bids is not throwing the exception – schwechel Oct 27 '20 at 13:41
  • Unfortunately, it doesn't cover the use case. It should be shorted based on the highest bid value of a product. – jeremiah valero Oct 27 '20 at 13:47
  • Based on your updated question, you are saying the list of products should be sorted ascending (lowest value on first) based on the highest bid amount for that product. Then you want this productList.OrderBy(x => x.Bids.Max(b => b.BidAmount)); Do note that products that are tied are not guaranteed to come back in the same order each time. – schwechel Oct 27 '20 at 13:55
  • Made a minor change to your Max answer, and it works now. productList.OrderByDescending(x => x.Bids.Max(y => (decimal?)y.BidAmount)), adding the nullable decimal solved the sequence error. – jeremiah valero Oct 27 '20 at 14:20