2009-09-11 37 views
4

我有一个linq查询需要将一个日期列从一行中拉出来。表达目前看起来像这样Linq - 从空值查询结果中提取值

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

的问题是,如果没有行是“签出”,查询将返回一个空并试图获得“指明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; 
})); 

但是,找到一些更简洁的东西会很好。有任何想法吗?

+1

+1:总是高兴地看到希望简明扼要的可维护性和可读性乡亲代码... – RSolberg 2009-09-11 17:19:01

回答

4

为什么不

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?); 
+0

现在,这很好,干净! – 2009-09-11 17:32:58

+0

不要忘记“作为日期时间?”,如果你不添加,你仍然会得到一个NRE。 – Ruben 2009-09-11 17:34:01

+0

非常好!谢谢Ruben! – jlembke 2009-09-11 17:36:38

1
var checkedOut = myObject.Where(s => s.CRAStatus.Description == "CheckedOut"); 
if (checkedOut.Count() > 0) { 
    var result = checkedOut.Max(s=> s.MyDate).MyDate; 
} 
+0

你可以替换checkedOut。用>!checkedOut.Empty()计数> 0,以获得更好的可读性 – 2009-09-11 17:28:38

+0

恐怕你不能在这种情况下。 IEnumerable 2009-09-11 17:32:27

3

一种选择是将default if empty设置为“空”实例(认为的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。

+0

对于DefaultIfEmpty()... +1不知道那个 – 2009-09-11 17:27:48

+0

当我找到该方法时,这是一个快乐,快乐的一天。该死,我的生活是空虚的。 – Will 2009-09-11 17:30:52

+0

puttin那个在我后面的口袋里。这很酷。 – jlembke 2009-09-11 18:09:14

1

扩展方法如何?

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);