Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get SecondOrDefault?

I have a simple linq lambda statement

Interactions = new BindableCollection<InteractionDTO>(ctx.Interactions.Where(x => x.ActivityDate > DateTime.Today)
   .Select(x => new InteractionDTO
   {
       Id = x.Id,
       ActivityDate = x.ActivityDate,
       subject = x.Subject,
       ClientNames = x.Attendees.Count == 1 ? x.Attendees.FirstOrDefault().Person.CorrespondenceName :
       x.Attendees.FirstOrDefault().Person.CorrespondenceName : "Multiple attendees"
    }));

This will give me the first Client Name, I'm trying to have it appear First 2 attendees followed by dots. I tried this

ClientNames = x.Attendees.Count == 1 ? 
             x.Attendees.FirstOrDefault().Person.CorrespondenceName :
             x.Attendees.FirstOrDefault().Person.CorrespondenceName +
             x.Attendees.Skip(1).FirstOrDefault().Person.CorrespondenceName + " ..."

But I get this error:

The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.

like image 446
Master Avatar asked May 09 '14 20:05

Master


2 Answers

You could try ordering first, as the message suggests.

I'm not sure what your Attendees class looks like, but assuming it has an ID field:

x.Attendees.OrderBy(a => a.ID)
           .Skip(1)
           .Select(a => a.Person.CorrespondenceName).FirstOrDefault() + " ..."

A couple other notes:

I swapped your Select and FirstOrDefault statements. The way you've currently got it, if FirstOrDefault() returns null, then Person.CorrespondenceName will throw an exception.

But now if no record is found, you'll end up with just "...". You might want to adjust your first Where clause to filter out records that have no correspondance name, and then change FirstOrDefault() to First().


EDIT:

That should steer you in the right direction (I hope). This may be more what you're looking for, assuming it can actually be translated into a valid SQL statement:

ClientNames = x.Attendees.Any()
                  ? x.Attendees.Count == 1
                      ? x.Attendees.Select(a => a.Person.CorrespondenceName).FirstOrDefault()
                      : x.Attendees.Count == 2
                          ? string.Join(", ", x.Attendees.OrderBy(a => a.ID).Take(2)
                                                         .Select(a => a.Person.CorrespondenceName).FirstOrDefault()
                          : string.Join(", ", x.Attendees.OrderBy(a => a.ID).Take(2)
                                                         .Select(a => a.Person.CorrespondenceName).FirstOrDefault() + " ..."
                  : "No client name available";
like image 83
Grant Winney Avatar answered Nov 06 '22 13:11

Grant Winney


// put this in your namespace...

public static class EnumerableExtension
{ 
    public static TSource SecondOrDefault<TSource>(this IEnumerable<TSource> source)
    {
        var iterator = source.GetEnumerator();
        if (iterator.MoveNext() && iterator.MoveNext() )            
            return iterator.Current;            
        else 
            return default( TSource );
    }
}

// Usage... var thing = list.SecondOrDefault();
like image 1
Christopher Grow Avatar answered Nov 06 '22 14:11

Christopher Grow