2017-07-17 91 views
0

我們有一個運行ASP.NET網站,它引發了一個NullReference-exception和一個根本不可能的堆棧跟蹤和行號。我自己也無法從頭到尾做出決定。Inexplicable NullReferenceException僅在生產中發生

它說:

Exception at ReportService.GetReport(String reportType) in ReportService.cs:line 1458 

這是有趣的,因爲這是該行:

var exports = new List<ReportExport>(); 

多虧了(很短)堆棧跟蹤,我可以看到錯誤被觸發GetReport函數,而不是在「GetAllUsers」或「GetAllUsersWithFilter」函數中,因爲我會在我的電子郵箱中收到不同的錯誤消息,或者我會在堆棧跟蹤中看到它。

所以我懷疑的行號是錯誤的,在這種情況下,只有一個另一種可能性,那就是這條線:

foreach (var userProfile in users) { 
     exports.Add(CreateUserProfile(userProfile)); 
    } 

卻怎麼users永遠是空?

滿(雖然簡單)的代碼就在這裏:

public function IList<ReportExport> GetReport(string reportType) { 
    try { 
     IQueryable<UserProfile> users = null; 
     switch (reportType) { 
      case "abc" : 
      users = GetAllUsersWithFilter(); 
      break; 
      case default: 
      users = GetAllUsers(); 
      break; 
     } 

     var exports = new List<ReportExport>(); 
     foreach (var userProfile in users) { 
      exports.Add(CreateUserProfile(userProfile)); 
     } 
    } catch (Exception ex) { 
    SendErrorMail("GetReport has failed", ex); /* I receive this error mail */ 
    } 

function IQueryable<UserProfile> GetAllUsers() { 
    try { 
     return dbContext.Users.Where(x => x.IsRegistered == true); 
    } catch (Exception ex) { 
     SendErrorMail("GetAllUsers", ex); /* I don't receive this e-mail */ 
     return null; 
    } 
} 

function IQueryable<UserProfile> GetAllUsersWithFilter() { 
    try { 
     return GetAllUsers().Where(x => x.ExtraFilter == true); 
    } catch (Exception ex) { 
     SendErrorMail("GetAllUsersWithFilter", ex); /* I don't receive this e-mail */ 
    } 
    } 

    function int GetNumberOfSessions(int userId) { 
    try { 
     return dbContext.Sessions.Count(x => x.UserId == userId); 
    } catch (Exception ex) { 
     SendErrorMail("GetNumberOfSessions", ex); /* I don't receive this e-mail */ 
    } 
    } 

    function ReportExport CreateUserExport(UserProfile user) { 
    try { 
     var cnt = GetNumberOfSessions(user.Id); 
     return new ReportExport() { 
      UserId = user.Id, 
      NumberOfSessions = cnt 
     } 
    } catch (Exception ex) { 
     SendErrorMail(("CreateUserExport", ex); 
    } 
    } 
+0

如果您正在生產中,那麼您可能在開啓優化時運行 - 因此行號會出錯。但是你正在捕獲Exception並返回null。你依靠返回數據 - 這可能不是真正的GetAllUsers – Andez

+0

的情況,但我會得到另一個不同的堆棧跟蹤錯誤郵件,不是嗎? –

+0

SendErrorMail如何處理多個傳入消息?它可以隱藏你嗎? – Dawnkeeper

回答

0

如果你在生產,那麼你可能與優化運行接通 - 因此行號將是錯誤的。

But how could users ever be null?

但你捕捉異常,然後返回null。您依賴於返回數據 - 這可能不是GetAllUsers中的情況。

function IQueryable<UserProfile> GetAllUsers() { 
    try { 
     return dbContext.Users.Where(x => x.IsRegistered == true); 
    } catch (Exception ex) { 
     SendErrorMail("GetAllUsers", ex); /* I don't receive this e-mail */ 
     return null; 
    } 
} 
+0

這絕對是真的,但是我得到的錯誤郵件指定了一行的堆棧跟蹤,其中帶有「GetReport()」。所以如果在GetAllUsers中發生錯誤,我應該得到兩封郵件。一個是因爲GetAllUsers中的異常,它會觸發「空」返回值,另一個是因爲GetReport函數失敗。我只收到一封電子郵件,指出GetReport函數失敗,這使我相信GetAllUsers必須成功 –

+0

捕獲其他函數中的異常的事實將隱藏您正在接收的未處理異常的異常。或者,也許SendErrorEmail中的某些內容是錯誤的並拋出異常?你可以發佈該代碼嗎?另外 - 它不喜歡你發佈整個代碼。dbContext在哪裏定義? – Andez

+0

確實,我沒有發佈所有的代碼,因爲它會讓我們太過分。我剛剛複製了生成錯誤的代碼。我還應該注意,這段代碼似乎在95%的時間內正常工作。 DbContext實際上完全在不同的服務中,我只是爲了簡潔而編輯它 –