2017-07-17 90 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实际上完全在不同的服务中,我只是为了简洁而编辑它 –