避免查询引发的EF中的null异常

时间:2014-10-09 15:54:56

标签: c# sql entity-framework nullreferenceexception

我有这样的查询:

        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()喜欢< / p>

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

因此,我的查询抛出一个空异常并且无法创建结果,如何处理此异常,例如,如果.NET检测到空值,则默认忽略它或使用默认值?

最好的问候。

3 个答案:

答案 0 :(得分:1)

由于您使用的是可以为空的日期,因此您可以尝试使用包含日期的值进行过滤,例如:

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

这将确保您不会获得任何带有空日期的记录。

正如我在评论中提到的,其他案件需要逐案处理。根据您显示的代码判断,也许您可​​以将Name处理为:

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

等等。

另一个例子:

如果您确实希望在DateOfMeeting为空时获取记录,则在后续部分中添加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()),

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

答案 1 :(得分: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时,您可以在使用.Select之前预测结果(使用.FirstOrDefault),这样您就无法访问Date可能是空值的属性。

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

无关:&#34;日历&#34;拼写为一个&#34; l&#34;而不是两个。

答案 2 :(得分: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;
相关问题