Sesame
Sesame

Reputation: 3410

OrderBy IEnumerable property of class

Given the following class, I would like to sort a list first by the FirstName property, and then by the PetNames property:

private class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string DateOfBirth { get; set; }
    public IEnumerable<string> PetNames { get; set; }
}

Ordering the list by just the FirstName works fine:

//...snip...//

people.OrderBy(a => a.FirstName);

//...snip...//

But I am having difficulty sorting the list based on the PetNames property as well:

people.OrderBy(a => a.FirstName)
      .ThenBy(a => a.PetNames);

This results in an exception:

EntityCommandCompilationException was unhandled by user code

EDIT:

What I meant to explain is that I am trying to first sort the list the FirstName property, and then sort the list of values in the PetNames property. For example:

FirstName---LastName---PetNames
Jim---------Jones------{Rex, Fido}
Bob---------Smith------{Pluto, Goofy}

when sorted, would turn into:

FirstName---LastName---PetNames
Bob---------Smith------{Goofy, Pluto}
Jim---------Jones------{Fido, Rex}

Any help on how to fix this will be greatly appreciated!

Upvotes: 1

Views: 2083

Answers (3)

coni2k
coni2k

Reputation: 2585

I would suggest you to do the PetNames sort operation, in get (or could be set) part of the property in your Person class;

public class Person
{

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string DateOfBirth { get; set; }

    // Do the sort order of the pet names while you get the value
    IEnumerable<string> petNames = new HashSet<string>();
    public IEnumerable<string> PetNames
    {
        get { return petNames.OrderBy(p => p); }
        set { petNames = value; } // Or sorting could be done in set as well
    }
}

Then again;

people.OrderBy(a => a.FirstName);

Upvotes: 0

Ant P
Ant P

Reputation: 25221

Based on your edit, the only way I can think to do this with a single lambda expression (and not just using a simple foreach for the pet names first) is to do this:

people.Select(p => { p.PetNames = p.PetNames.OrderBy(o => o); return p; })
      .OrderBy(p => p.FirstName);

But I don't really see what's wrong with just doing:

foreach(var person in people)
{
    person.PetNames = person.PetNames.OrderBy(o => o);
}

var sorted = people.OrderBy(p => p.FirstName);

I'm sure there probably is an elegant way of writing this in one lambda expression that doesn't use an explicit anonymous function like that but I'm having trouble coming up with it so I imagine it would be pretty cryptic.

Upvotes: 0

Shay
Shay

Reputation: 1778

You will need to convert PetNames to a value that Linq-to-Entities can compare it by. Maybe something like this:

people.OrderBy(a => a.FirstName)
    .ThenBy(a => String.Join("", a.PetNames.ToArray()));

UPDATE: According to your question clarification:

people.Select(p => new Person()
{
    FirstName = p.FirstName,
    LastName = p.LastName,
    DateOfBirth = p.DateOfBirth,
    PetNames = p.PetNames.OrderBy(n => n)
})
.OrderBy(a => a.FirstName);

Upvotes: 3

Related Questions