Entity Framework 当实体不是 public 时不加载相关数据

Entity Framework does not load related data when entities are not public

我在控制台应用程序中有两个 类。

Person:

 class Person {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public virtual ICollection<Order> Orders { get; set; }

        public override string ToString() {
            return Id + " " + FirstName + " " + LastName; 
        }
    }

Order:

 class Order {
        //Id to domyslna nazwa na identyfikator -> klucz glowny
        public int Id { get; set; }
        public int Total { get; set; }
        public virtual Person Owner { get; set; }

        public override string ToString() {
            return Id + " " + Total;
        }
    }

我的dbContext是:

    class ApplicationDbContext : DbContext {
        public DbSet<Person> Persons { get; set; }
        public DbSet<Order> Orders { get; set; }
        public ApplicationDbContext()
            : base("Olek2") {
                Configuration.LazyLoadingEnabled = true;
                Configuration.ProxyCreationEnabled = true;

        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
       public static ApplicationDbContext Create() {
        return new ApplicationDbContext();

      }
}

我通过 update-database 生成了新的数据库。

Main 方法中,我尝试获取 Person 然后访问人员的订单,但我在 p1.Orders.Count() 上遇到空指针异常。我将属性设为虚拟,还启用了延迟加载,我不知道问题出在哪里。

    static void Main(string[] args) {
        ApplicationDbContext context = new ApplicationDbContext(); 
        Person p1 = context.Persons.Find(1);
        Console.WriteLine(p1); // THIS WORKS
        Console.WriteLine(context.Orders.Count()); //THIS IS 1
        Console.WriteLine(p1.Orders.Count()); //EXCEPTION HERE 
        Console.ReadKey();
    }

还有我的Seed方法:

protected override void Seed(ApplicationDbContext context) {
        Person person = null;

        if (!context.Persons.Any()) {
             person = new Person() {  FirstName = "Alaaaaa", LastName = "Kowlaska" };
            context.Persons.AddOrUpdate(person);
        }
        if (!context.Orders.Any()) {
            context.Orders.AddOrUpdate(new Order() { Total = 100, Owner = person });
        }

        context.SaveChanges();
    }

编辑:

我有一种预感,它与 public static ApplicationDbContext Create() 在我的控制台应用程序(失败)中有 0 个引用(VS2013 指示)有关。

在我的 ASP.NET-MVC(工作正常)中,它被引用:

 public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context and user manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);

        ....
       } 

EDIT2 我有预感它似乎没有连接。

由于您的实体未使用 public 修饰符标记(这意味着默认情况下编译器会将它们设为 internal),因此 EF 将无法为实体类型生成代理。

查看 EntityProxyFactorysource code(第 577 行):

private static bool CanProxyType(EntityType ospaceEntityType)
{
    TypeAttributes access = ospaceEntityType.ClrType.Attributes & TypeAttributes.VisibilityMask;

    ConstructorInfo ctor = ospaceEntityType.ClrType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, Type.EmptyTypes, null);
    bool accessableCtor = ctor != null && (((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public) ||
                                          ((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family) ||
                                          ((ctor.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem));

    return (!(ospaceEntityType.Abstract ||
             ospaceEntityType.ClrType.IsSealed ||
             typeof(IEntityWithRelationships).IsAssignableFrom(ospaceEntityType.ClrType) ||
             !accessableCtor) &&
             access == TypeAttributes.Public);
}

你可以清楚地注意到CanProxyType的最后一行检查实体类型是否确实是public

现在,由于您没有初始化 Person.Orders(在构造函数中或其他任何地方)并且不涉及代理来拦截对 Orders 的调用(初始化它并检测与 Order.Person),你最终得到 Orders 为 null 并抛出 NRE。