类链接时的实体框架dbSet.Add

时间:2015-02-20 16:39:12

标签: c# asp.net entity-framework

问题
当我试图添加一个链接到EF中其他对象的对象时,为什么dbSet.Add方法不起作用?

详情
有一些背景知识:我是EF的初学者,我正在学习如何使用Code First来开发数据模型。

我正在使用VS2013 Express,通过NuGet将Entity Framework 6添加到基本的MVC项目中。

我为我的数据模型创建了三个类:Class_oneOnlyClass_manyClass_severalClass_oneOnly与其他两个类具有一对多关系,而另外两个类彼此之间具有多对多关系。

我正在使用Code First,但为了解释这些关系,这里是一个实体关系图(我在一个单独的项目中绘制了这个,所以Code-First和Model-First之间没有任何干扰。此外,没有预生成的代码......虽然也许我应该这样做,我正在努力学习Code First):
enter image description here

我可以创建每个类的新实例。

但是,当我尝试执行DbSet.Add method向数据库添加class_many的新实例时,我收到错误“NullReferenceException未被用户代码处理。”

这是事实,我在try-catch块中没有这个。 但是,即使使用try-catch块,它仍然无法解释异常
"An exception of type 'System.NullReferenceException' occurred in EF Test Code First.dll but was not handled in user code. Additional information: Object reference not set to an instance of an object."

主要问题是:为什么抛出一个空引用,如果此时所有三个类都被定义了?不应该EF将属性分配给类通过Code First中定义的关系链接?

我应该在代码中添加一些内容才能使其正常工作吗?

代码示例
设置EF DbSet:

using System.Data.Entity;

namespace EF_Test_Code_First.Models
{
    public class Context : DbContext
    {
        public Context()
            : base("name=MyContext")
        {
        }

        public DbSet<Class_many> Class_manys { get; set; }
    }
}

班级定义:

public class Class_oneOnly
{
    [Key]
    public string SN { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Class_many> Class_manys { get; set; }
    public virtual ICollection<Class_several> Class_severals { get; set; }
}

public class Class_several
{
    public int ID { get; set; }
    public string Name { get; set; }

    public Class_oneOnly Class_oneOnly { get; set; }
    public virtual ICollection<Class_many> Class_manys { get; set; }
}

public class Class_many
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual Class_oneOnly Class_oneOnly { get; set; }
    public virtual ICollection<Class_several> Class_severals { get; set; }
}

...最后但并非最不重要的是,我的测试代码设置了类并尝试使用DbSet.Add方法。 Context dbContext从控制器传递(并且是静态Context,如上面所定义的那样):

public void myTest(Context dbContext)
{
    /* assign property values to oneOnly,
        * of which there is only one of these
        * in each many and each several.
        */

    Class_oneOnly oneOnly = new Class_oneOnly()
    {
        SN = "1",
        Name = "oneOnly1"
    };

    /* make sure ids are unique as the following
        * 'for' loop is iterated through
        */
    int startid;
    if (dbContext.Class_manys != null && dbContext.Class_manys.Count() > 0){
        startid = dbContext.Class_manys.Count();
    }
    else{
        startid = 0;
    }

    /* create and fill class_many and
        * class_several objects, using a new id.
        */
    for (int i = startid; i < 5; i++)
    {
        /* assign property values to many
            * and several.
            */
        Class_many many = new Class_many()
        {
            ID = i,
            Name = "many" + i.ToString()
        };

        Class_several several = new Class_several()
        {
            ID = i,
            Name = "several" + i.ToString()
        };

        /* assign further property values
            * that use navigation properties
            * to link between classes.
            */
        many.Class_oneOnly = oneOnly;
        several.Class_oneOnly = oneOnly;
        many.Class_severals.Add(several);

        /* add to EF
            */
        /*************************
            * Error occurs at this line
            *************************
            */
        dbContext.Class_manys.Add(many);
    }

    /* save
        */
    dbContext.SaveChanges();
}

我可以根据要求提供项目其他部分的代码。

1 个答案:

答案 0 :(得分:3)

是的,所以我重新创建了你的项目并认为我发现了这个问题。第一件事:我建议您使用DbContext NOT 作为静态,而是使用using块。如果您仍有问题,那就是我尝试和排除故障的方法,以及我一直试图做的事情。如果你有一个全球性的静态背景,我想你会发现以后追查问题会更加困难。

我在many.Class_severals.Add(several);上遇到了一个空引用错误,而不是你说的那个。我确实使用了一个快速的Winforms项目进行故障排除,但是如果您使用上面发布的代码,我不确定为什么/如何获得不同的错误...无论如何,您有两个选择:您需要创建一个新集合,如果它尚未初始化,你可以在构造函数中或在我的偏好中在getter中完成。

public class Class_many
    {
        public int ID { get; set; }
        public string Name { get; set; }

        private ICollection<Class_several> _severals;

        public virtual Class_oneOnly Class_oneOnly { get; set; }
        public virtual ICollection<Class_several> Class_severals { get
        {
            if (_severals == null) {_severals = new List<Class_several>();}
            return _severals;
        }
            set { _severals = value; }
        }
    }