为什么导航属性在其类是私有时不会填充?

时间:2016-01-20 13:20:46

标签: c# entity-framework

我有这个简单的模型:

class Parent
{
   public int Id { get; set; }

   public virtual ICollection<Child> Children { get; set; }
}

class Child
{
   public int Id { get; set; }
   public int ParentId { get; set; }

   public virtual Parent Parent { get; set; }
}

class MyContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Children { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Child>().HasRequired(s => s.Parent).WithMany(s => s.Children).HasForeignKey(s => s.ParentId);

        base.OnModelCreating(modelBuilder);
    }
}

当我使用MyContext如下所示时,我得到空引用异常,因为child.Parent为空

var context = new MyContext();
var child = context.Children.First();
var parentId = child.Parent.Id;              // Parent == null

要解决此问题,我必须将ParentChild类的访问修饰符更改为public

为什么需要?或者这只是一个错误?

2 个答案:

答案 0 :(得分:5)

这不是一个错误,您正在使用名为Lazy Loading的实体框架功能,要使用它,您需要满足在此link中可以找到的一些要求。其中一个要求是您的实体类必须是public。在该链接中,您将找到正确的解释,说明为什么您应该满足这些要求,但总的来说,您的问题是因为EF无法从您的实体创建代理类,因为您无法使用延迟加载。您已经满足了延迟加载的主要要求,导航属性必须是virtual,但首先您必须满足EF创建代理类所需的要求。

作为附加资源,我建议您查看此msdn页面,您可以在其中找到使用EF加载相关实体的所有方法。

答案 1 :(得分:2)

首先,要清除一些内容:您的课程不是<div class="table"> <div class="td"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut libero et odio rhoncus luctus a a nunc. Etiam et dolor magna. Vivamus semper mi in porta pellentesque. </div> <div class="td"> <img alt="" src="http://placehold.it/120x148" style="width: 120px; height: 148px;" /> </div> </div>,而是private。您不能将顶级类型(非嵌套类型)声明为私有类型(有关详细信息,请参阅MSDN Access Modifiers)。

其次,默认情况下,首先启用延迟加载代码。正如octaviocci所提到的,如果你期望使用Lazy Loading,你需要公开它们:它只是要求的一部分。通过将导航属性声明为internal,您告诉EF您希望使用延迟加载。如果您不想,可以(应该)删除virtual关键字。然后,在获取实体时,使用virtual方法急切地加载相关实体。

Include