当实体不公开时,实体框架不会加载相关数据

时间:2015-04-12 10:20:12

标签: c# entity-framework entity-framework-6.1

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

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  我有预感,无论如何似乎都没有联系。

1 个答案:

答案 0 :(得分:2)

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

查看EntityProxyFactory的{​​{3}}(第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的调用(初始化它并检测与{的关联) {1}}),最终Order.Person为空,并抛出NRE。