2014-10-09 27 views
0

抛出我有这样的查询:避免在EF空的异常,通过查询

 result = 
      firstIdeaRepository.FindBy(
       i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end) 
           .AsEnumerable() 
           .Select(j => new RptListOfCompanyBasedOnFirstIdeaState() 
            { 
             Name = 
              companyRepository.FindBy(i => i.UserId == j.UserId) 
                  .FirstOrDefault() 
             DateOfMeeting = 
              calenderRepository.ConvertToPersianToShow(
               meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id) 
                   .FirstOrDefault() 
                   .Date), 
             DateOfExit = 
              calenderRepository.ConvertToPersianToShow(j.DateOfExit.Value), 
             ReasonOfExit = j.ReasonOfExit, 
            }).ToList(); 

    return result; 

正如你可以看到我使用FirstOrDefault()j.DateOfExit.Value,有时我的日期没有任何价值或有时我其他变量是空过,因为我使用firstordefaut()

companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault(). 

所以我的查询会引发空异常,并不能产生结果,我该如何处理这个异常以及例如,如果.NET检测到空值我们默认或忽略它这是默认值吗?

此致敬礼。

+0

其中我可以设置第一个或默认值? – 2014-10-09 16:01:19

+0

你可以在'.FirstOrDefault()'之前的调用链中使用'.DefaultIfEmpty()'。 – 2014-10-09 16:04:39

+0

@martin_costello:'.DefaultIfEmpty()'不会对引用类型有帮助,默认值为null。 – Mrchief 2014-10-09 16:05:47

回答

1

我会做如下修改:

result = 
    firstIdeaRepository.FindBy(
     i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end) 
      .AsEnumerable() 
      .Select(j => new RptListOfCompanyBasedOnFirstIdeaState() 
      { 
       Name = 
        companyRepository.FindBy(i => i.UserId == j.UserId) 
         .FirstOrDefault() 
       DateOfMeeting = 
        callenderRepository.ConvertToPersianToShow(
         meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id) 
          // project a new sequence first, before calling `FirstOrDefault`: 
          .Select(s => s.Date) 
          .FirstOrDefault(), 
       DateOfExit = 
        j.DateOfExit.HasValue ? 
         callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) : 
         null,      
        ReasonOfExit = j.ReasonOfExit, 
       }).ToList(); 

当您使用FirstOrDefault,还有你会得到null回来(在引用类型的情况下)的可能性,所以你需要计划为在你的代码中。

例如,分配DateOfMeeting时,你可以使用.FirstOrDefault前投影结果(使用.Select),让你没有访问过什么可能是一个空值Date属性。

至于DateOfExit,我已经使用条件运算符来决定是否调用calendarRepository的方法。这假定DateOfExit是可空的。

无关:“日历”拼写为一个“l”而不是两个。

+0

谢谢亲爱的我把它从两个改为一个,谢谢 – 2014-10-09 16:20:50

1

由于您使用可空的日期,你可以通过有日期,喜欢的东西值尝试过滤:

.FindBy(s => s.FirstIdeaId == j.Id && s.Date.HasValue) 

这将确保你不会用空日期的任何记录。

正如我在评论中提到的,其他情况需要逐案处理。由您所示的代码来看,也许你可以处理Name为:

Name = companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault() ?? "anonymous"; 

等。

又如:

如果你想要得到的记录即使DateOfMeeting为null,则在后续部分添加一张支票HasValue或将其默认为某个日期:

DateOfExit = j.DateOfExit.HasValue ? 
       callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) 
       : (DateTime)null, // you need to make `DateOfExit` nullable and then handle that downstream 

// or (default with current date) 
DateOfExit = j.DateOfExit.HasValue ? 
       callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) 
       : callenderRepository.ConvertToPersianToShow(DateTime.Now), 

// or (default with empty date) 
DateOfExit = j.DateOfExit.HasValue ? 
       callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) 
       : callenderRepository.ConvertToPersianToShow(new DateTime()), 

的道德故事情节:找出什么默认值应该为空的情况下,然后在调用FirstOrDefault()时在查询中相应替换。

+0

那么其他的null异常呢?像companyRepository.FindBy(i => i.UserId == j.UserId) .FirstOrDefault() – 2014-10-09 16:03:18

+1

我打算把这个添加到我的答案中。所以基本上其他人必须在个案的基础上接受。你必须决定_how_你想在这些情况下处理空值。例如,对于名称,用一个默认值(空字符串或Noname)替换它,以便在访问它们时不会收到空引用异常。 – Mrchief 2014-10-09 16:05:03

0

最广泛的解决方案是在查询中使用null objectDefaultIfEmpty<T>(T DefaultValue)方法。一个例子是:

var defaultMeeting = new Meeting() { Date = new DateTime() }; 

var dateOfMeeting = meetingRepository.FindBy(s => s.FirstIdeaId == j.Id) 
     .DefaultIfEmpty(defaultMeeting) 
     .FirstOrDefault() 
     .Date;