对象引用未设置为对象的实例 - 多个项目(MVC)

时间:2016-02-22 12:44:28

标签: asp.net-mvc-5 entity-framework-6 solid-principles ef-migrations

我正在使用Contoso大学教程并尝试模块化尝试(模型,DAL和WebUI的单独项目 - 附图中的顶部图片)和单个项目(包含所有图层 - 底部图片)。在这两种情况下,解决方案都可以正确编译。但是,当我在Web浏览器中转到学生的详细信息部分时,模块化项目在我转到第二个断点时会引发错误,开始:

异常详细信息:

  

System.NullReferenceException:未将对象引用设置为对象的实例。

将相同的模型传递到每个项目的视图中,

@model ContosoUniversity.Models.Student

在行之后出现空引用异常:

@foreach (var item in Model.Enrollments){ 

我认为它可能是ContosoUniversity.Models项目和ContosoUniversity项目中的Models文件夹之间的命名空间冲突,但重命名文件夹无法解决此问题。是否存在与多个项目相关的其他内容会导致在此处遇到空值(Enrollments.cs未发送到模型),而不是单个项目? 如果它在代码中更深层次,我可以跟进完整的视图代码和模型类。

Screenshot of working and non working solutions in VS2015Community

1 个答案:

答案 0 :(得分:3)

由于这对新开发人员来说是一个常常令人困惑的错误,我已经创作了一个post on my blog来解释错误的含义以及如何调试它。 TL; DR:Object reference not set to an instance of an object是一个运行时错误(因此你的项目编译好的原因),当你期望一个变量成为一个特定类的实例时,它就会发生,但它实际上在运行时解析为null。

这通常发生在您从数据库中选择对象但没有匹配时,或者您忽略了在模型上初始化需要初始化的属性(如列表)。基于您发布的代码行,我的猜测是模型本身是空的(可能是因为它来自数据库而您在将其发送到视图之前没有检查null),或{{1如果您的模型是实体类的实例,则属性为null,因为您忽略了初始化它,或者它没有标记为Enrollments

每当您从数据库中请求特定对象时,应始终检查null并正确处理。例如,如果您正在处理“详细”操作,则代码应如下所示:

virtual

如果模型上有list-style属性,则应始终通过类构造函数或自定义getter初始化它:

public ActionResult Detail(int id)
{
    var foo = db.Foos.Find(id); // potentially null, if no matching id
    if (foo == null)
    {
        return new HttpNotFoundResult();
    }

    return View(foo);
}

或者

public class Foo
{
    public Foo()
    {
        Bars = new List<Bar>();
    }

    public List<Bar> Bars { get; set; }
}

如果你正在使用C#6,最后一个可以简化为:

public class Foo
{
    private List<Bar> bars;
    public List<Bar> Bars
    {
        get
        {
            if (bars == null)
            {
                bars = new List<Bar>();
            }
            return bars;
        }
        set { bars = value; }
    }
}

最后,如果您正在处理实体框架POCO,那么这不是必需的,只要该属性为public class Foo { public List<Bar> Bars { get; set; } = new List<Bars>(); }

virtual

作为延迟加载工具的一部分,Entity Framework会自动覆盖该属性,使其永远不会为null,只有空集合才真正没有。但是,如果忽略public virtual ICollection<Bar> Bars { get; set; } 关键字,EF无法执行必要的覆盖来处理此问题。

长和短,你需要找出你希望有一个实际值的变量为null,然后进行适当的空值检查(不管这是个好主意)还是找出为什么它为null而不是您期望的价值。