2014-10-09 31 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;