我目前正在通过Code First方法学习实体框架(EF)。我想在新创建的数据库(即由EF创建)上建模Professor
和Class
之间的简单一对多关系。
在我的模型中,Professor
有一个Class
es的集合。 Class
始终有一个Professor
与之关联(即相应的属性永远不为空)。我可以创建并存储Class
和关联的Professor
,但是当我访问从数据库中检索到的Classes
的{{1}}属性时,它是空的。但是,可以从Professor
导航到Class
。
考虑以下模型:
Professor
在我的主要方法中,我创建并访问我的数据:
class Class
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Professor Professor { get; set; }
}
class Professor
{
public int Id { get; set; }
public string Name { get; set; }
private ICollection<Class> classes = null;
public virtual ICollection<Class> Classes
{
get { return classes ?? (classes = new HashSet<Class>()); }
set { classes = value; }
}
}
class ClassManager : DbContext
{
public DbSet<Professor> Professors { get; set; }
public DbSet<Class> Classes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Class>().HasRequired(c => c.Professor);
}
}
输出结果为:
using (ClassManager db = new ClassManager())
{
Professor p = new Professor() { Name = "McTest" };
Class c = new Class() { Title = "Testing Tests", Professor = p };
p.Classes.Add(c);
db.Professors.Add(p);
db.Classes.Add(c);
Console.WriteLine(db.SaveChanges() + " change(s) saved.");
}
using (ClassManager db = new ClassManager())
{
foreach (Professor p in db.Professors)
Console.WriteLine("Prof. " + p.Name + " gives " + p.Classes.Count
+ " classes.");
foreach (Class c in db.Classes)
Console.WriteLine(c.Title + " (Prof. " + c.Professor.Name + ")");
}
生成的数据库架构是:
3 change(s) saved.
Prof. McTest gives 0 classes.
Testing Tests (Prof. McTest)
如您所见,table Classes
column Id (PK, int, not null)
column Title (nvchar(max), null)
column Professor_Id (FK, int, not null)
table Professors
column Id (PK, int, not null)
column Name (nvchar(max), null)
集合属性不会出现在架构中的任何位置。那是为了吗?
有人可以对此有所了解吗?我发现的所有示例都不会详细介绍集合属性。
答案 0 :(得分:7)
好的,经过几个小时的搜索,我找到了解决方案。在查询数据库时,似乎必须明确指示EF加载实体的集合属性:
foreach (Professor p in db.Professors.Include("Classes"))
Console.WriteLine("Prof. " + p.Name + " gives " + p.Classes.Count
+ " classes.");
Include
方法可以做到这一点。
答案 1 :(得分:1)
我的主要代码中使用两个分隔的语句是故意的。如果我将它们合并在一起,Classes属性突然不为空,但我不明白为什么。
如果将2合并为1,则“查询”存储在内存中的本地实体,而不是数据库。
在您的第一个上下文中,您无需将professor
和class
添加到上下文中。只需添加教授,class
也将被保存。
检查数据库架构并确保实体已正确映射到数据库。
最后,将Professor
类更改为
class Professor
{
public Professor()
{
Classes = new List<Class>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Class> Classes {get; set;}
}
我怀疑延迟加载被is null逻辑打败以返回一个散列集。