NullReferenceException 来自生产中我无法在本地重现的任何方法

NullReferenceException from Any method in production that I cannot reproduce locally

提问人:user2609980 提问时间:7/26/2014 最后编辑:user2609980 更新时间:7/26/2014 访问量:258

问:

当我查看我们的 MVC4 网站时,除其他外,该网站可用于制作时间表并转到 /Timetable,我看到错误消息:

System.NullReferenceException:对象引用未设置为实例 对象。(...)

堆栈跟踪: [NullReferenceException:对象引用未设置为 对象。
ASP._Page_Views_Timetable_Index_cshtml.b__5 (附表 s) +54
System.Linq.Enumerable.Any(IEnumerable2 谓词) +146 ASP._Page_Views_Timetable_Index_cshtml。执行() +4057 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +198 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +104 System.Web.WebPages.StartPage.RunPage() +17


System.Web.WebPages.StartPage.ExecutePageHierarchy() +64 (...)
1 source, Func

这是不可取的。不幸的是,我无法在生产中将编译模式放入调试中,并且在本地我无法重现该错误。我确实想修复它,我希望这里有人可以帮助我。我将提供我解决问题的尝试,并希望您愿意一起思考:

查看上面的堆栈跟踪,我看到一个调用,控制器上只有两个调用,一个调用。Any()Any()Timetable/Index.cshtml

我们有一个 Schedule 和一个 Proposal 模型:(Schedule 用于存储 Date、User 和 State,如果一个用户想要与其他用户更改日期,则使用 Proposal)。

public class Schedule : IValidatableObject {
    [Key]
    public int ScheduleId { get; set; }
    public DateTime Date { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
    public ScheduleState State { get; set; }
    public virtual ICollection<Proposal> ProposalsAsSender { get; set; }
    public virtual ICollection<Proposal> ProposalsAsReceiver { get; set; }
}

public class Proposal {
    public int ProposalId { get; set; }
    public ProposalState State { get; set; }
    [InverseProperty("ProposalsAsSender")]
    public virtual Schedule SenderSchedule { get; set; }
    [InverseProperty("ProposalsAsReceiver")]
    public virtual Schedule ReceiverSchedule { get; set; }
}

模型上有以下两种方法:Proposal

public ICollection<Proposal> GetAssociatedProposals()
{
    return ProposalsAsSender.Concat(ProposalsAsReceiver).ToList();
}

public ICollection<Proposal> GetActiveAssociatedProposals()
{
    return GetAssociatedProposals()
            .Where(p => p.State == ProposalState.Active)
            .Where(p => p.ReceiverSchedule.State == ScheduleState.Active)
            .Where(p => p.SenderSchedule.State == ScheduleState.Active)
            .ToList();
}

我在本地看到的是,此方法始终返回一个空列表,而不是.(它能回来吗?nullnull

还有一种方法:TimetableController

[HttpGet]
public ActionResult Index()
{
    var dates = Schedule.GetCorveeDatesNextThirtyDays(); // returns dates that are not weekends
    var schedulesNextThirtyDays = db.Schedules.Where(s =>  
                             dates.Contains(s.Date)).ToList();

    var schedules = schedulesNextThirtyDays.Where(s => s.State == 
                             ScheduleState.Active).ToList();

    if (!schedules.Any(s => s.Date.Equals(DateTime.Now.Date))) //Any in controller
    {
        var todays_schedule = schedulesNextThirtyDays.Where(s => s.State == 
                ScheduleState.Completed).FirstOrDefault(s => dates.Contains(s.Date));
        if(todays_schedule != null)
            schedules.Add(todays_schedule);
    }

    return View(new DatesAndSchedulesViewModel(dates, schedules));
}

其中由构造函数中设置的 和 组成。DatesAndSchedulesViewModelICollection<Schedule> SchedulesICollection<DateTime> Dates

在具有 Timetable 视图上,我们有以下代码,该代码在检查后发生:DatesAndSchedulesViewModelModelschedule != null

@if (Model.Schedules.Any(s => s.User.Name.Equals(User.Identity.Name))) //First Any() on view
{
    if (schedule.State == ScheduleState.Active)
    {
        if (schedule.GetActiveAssociatedProposals().Any()) //Second Any() on view
        {
            <span>Do something</span>
        }
    }
}

我知道如果在 上完成,Linq 可能会抛出 NullReferenceException。我想知道的是,在视图上是否有可能返回,从而抛出上面的异常?或者可以在控制器上做一个检查?Any()nullschedule.GetActiveAssociatedProposals()Timetablenullif (!schedules.Any(s => s.Date.Equals(DateTime.Now.Date)))null

如果是这样,则可以通过在执行检查之前检查某些属性是否存在来解决该问题。我希望有人能告诉我是否确实如此,并给我一个如何实现 -checks 的开始!nullnull

C# LINQ ASP.NET-MVC-4 nullReferenceException

评论

0赞 Steve Newton 7/26/2014
我记得这种错误的痛苦,以及我花在尝试重现用户看到的某些错误上的时间。Cameron 在下面的钱上,但要分享的是,我们现在已经在生产中实现了 Intellitrace,虽然只有 VS Ultimate 可用,但我永远不会回去,它减少了太多在调试上浪费的时间。查看 stacktrace 的错误,然后双击转到导致问题的代码行。值得一看,以备将来考虑!

答:

3赞 Cameron MacFarland 7/26/2014 #1

Any 可以返回 null,但在这种情况下,是 lambda 抛出 null。

从堆栈跟踪:

ASP._Page_Views_Timetable_Index_cshtml.b__5(Schedule s) +54

b__5表示是由 内部使用的 lambda 创建的内部类。Any

if (!schedules.Any(s => s.Date.Equals(DateTime.Now.Date)))

我的猜测是 null,所以列表不是空的,而是包含一个 null 元素。s

编辑:哎呀,错了Any

@if (Model.Schedules.Any(s => s.User.Name.Equals(User.Identity.Name)))

这更有意义。 可以是 null,也可以是 null。UserName

评论

0赞 user2609980 7/26/2014
b_5表示内部类。哇,你怎么知道你不介意我问?问了这个问题,该表不允许所有列都使用 NULL,所以我不明白怎么可能包含 null 元素?Schedulesdb.Schedules.Where(s => dates.Contains(s.Date)).ToList()
0赞 user2609980 7/26/2014
此外,'s 和 's 不能为 NULL。ScheduleUserIdUserName
1赞 Cameron MacFarland 7/26/2014
@user2609980我只认识 C# 编译器用于 lambda 的名称。双下划线是一个好兆头。
0赞 user2609980 7/26/2014
对 null 进行 null 检查会有所帮助吗?喜欢在?s@if (Model.Schedules.Any(s => s.User != null && s.User.Name != null && s.User.Name.Equals(User.Identity.Name)))
0赞 Cameron MacFarland 7/26/2014
@user2609980,是的,这是我开始在可疑区域周围放置空守卫并希望解决问题的情况之一。