问题:
当我试图添加一个链接到EF中其他对象的对象时,为什么dbSet.Add
方法不起作用?
详情:
有一些背景知识:我是EF的初学者,我正在学习如何使用Code First来开发数据模型。
我正在使用VS2013 Express,通过NuGet将Entity Framework 6添加到基本的MVC项目中。
我为我的数据模型创建了三个类:Class_oneOnly
,Class_many
和Class_several
。 Class_oneOnly
与其他两个类具有一对多关系,而另外两个类彼此之间具有多对多关系。
我正在使用Code First,但为了解释这些关系,这里是一个实体关系图(我在一个单独的项目中绘制了这个,所以Code-First和Model-First之间没有任何干扰。此外,没有预生成的代码......虽然也许我应该这样做,我正在努力学习Code First):
我可以创建每个类的新实例。
但是,当我尝试执行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();
}
我可以根据要求提供项目其他部分的代码。
答案 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; }
}
}