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

时间:2014-07-26 12:14:01

标签: c# linq asp.net-mvc-4 nullreferenceexception

当我查看我们的MVC4网站时,其中包括可用于制作时间表并转到/时间表,我看到错误消息:

  

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

     

堆栈跟踪:   [NullReferenceException:对象引用未设置为的实例   对象。]
  ASP._Page_Views_Timetable_Index_cshtml.b__5(附表s)+54
  System.Linq.Enumerable.Any(IEnumerable 1 source, Func 2谓词)   +146 ASP._Page_Views_Timetable_Index_cshtml.Execute()+ 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(...)

这是不可取的。不幸的是,我无法将编译模式放入生产调试中,而本地我无法重现错误。我确实想解决这个问题,我希望有人可以帮助我。我会尝试解决这个问题,并希望你愿意一起思考:

查看上面的堆栈跟踪,我看到Any()来电,Any()上只有两个Timetable/Index.cshtml来电,而控制器中只有一个。{/ p>

我们有一个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();
}

我在本地看到的是这个方法总是返回一个空列表,但不是null。 (可以返回null吗?)。

还有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));
}

DatesAndSchedulesViewModel由构造函数中设置的ICollection<Schedule> SchedulesICollection<DateTime> Dates组成。

DatesAndSchedulesViewModelModel的时间表视图中,我们在schedule != 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的Any()如果在null上完成,则会抛出NullReferenceException。我想知道的是schedule.GetActiveAssociatedProposals()视图中的Timetable是否可能返回null,因此抛出上述异常?或者控制器中的if (!schedules.Any(s => s.Date.Equals(DateTime.Now.Date)))可以对null进行检查吗?

如果是这样,可以通过在执行检查之前检查某些属性是否为null来解决问题。我希望有人可以告诉我是否确实如此,并开始介绍如何实施null - 检查!

1 个答案:

答案 0 :(得分:3)

任何都可以返回null,但在这种情况下,它是抛出null的lambda。

来自你的堆栈跟踪:

ASP._Page_Views_Timetable_Index_cshtml.b__5(Schedule s) +54

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

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

我的猜测是s为空,因此列表不为空,但包含null元素。

编辑:糟糕,错误Any

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

这更有意义。 <{1}}可以为null,或User可以为null。