Linq - извлечение значения из нулевого результата запроса - PullRequest
4 голосов
/ 11 сентября 2009

У меня есть запрос linq, который должен извлечь столбец даты из строки. Выражение в настоящее время выглядит так

myObject.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault().MyDate)

Проблема заключается в том, что если нет строк с «CheckedOut», запрос возвратит ноль, а попытка получить «MyDate» вызовет исключение. У нас есть несколько подробных решений, таких как:

.ForMember(dest => dest.CheckOutDate, opt => opt.MapFrom(src => {
    var temp = src.CRAStatusChangeEvents.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault();
    return temp == null ? temp.MyDate : null;
}));

Но было бы неплохо найти что-то более краткое. Есть идеи?

Ответы [ 4 ]

4 голосов
/ 11 сентября 2009

Почему бы не

myObject.OrderByDescending(s=> s.MyDate)
        .Where(s => s.CRAStatus.Description == "CheckedOut")
        .Select(s => s.MyDate as DateTime?)
        .FirstOrDefault();

или

myObject.Where(s => s.CRAStatus.Description == "CheckedOut")
        .Max(s => s.MyDate as DateTime?);
3 голосов
/ 11 сентября 2009

Один из вариантов - установить по умолчанию, если пусто , в «пустой» экземпляр (представьте себе string.Empty - это известный экземпляр, представляющий пустой результат):

var date = (myObject
    .OrderByDescending(s=> s.MyDate)
    .Where(s => s.CRAStatus.Description == "CheckedOut")
    .DefaultIfEmpty(MyObject.Empty)
    .FirstOrDefault()).MyDate;

Вот фрагмент, который показывает, как это работает:

var strings = new string[]{"one", "two"};
var length = 
    (strings.Where(s=>s.Length > 5)
    .DefaultIfEmpty(string.Empty)
    .FirstOrDefault()).Length;

запустите его и длину 0. Удалите строку DefaultIfEmpty, и вы получите NRE.

1 голос
/ 11 сентября 2009

Как насчет метода расширения?

static class MyObjectEnumerableExtensions
{
    public static TMember GetMemberOfFirstOrDefault<TMember>(this IEnumerable<MyObject> items, Func<MyObject, TMember> getMember)
    {
        MyObject first = items.FirstOrDefault();
        if (first != null)
        {
            return getMember(first);
        }
        else
        {
            return default(TMember);
        }
    }
}

Пример использования:

List<MyObject> objects = new List<MyObject>();
objects.Add(new MyObject { MyDate = DateTime.MinValue });

var filteredObjects = from s in objects where s.MyDate > DateTime.MinValue select s;

DateTime date = filteredObjects.GetMemberOfFirstOrDefault(s => s.MyDate);

Console.WriteLine(date);
1 голос
/ 11 сентября 2009
var checkedOut = myObject.Where(s => s.CRAStatus.Description == "CheckedOut");
if (checkedOut.Count() > 0) {
   var result = checkedOut.Max(s=> s.MyDate).MyDate;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...