2015-04-12 86 views
2

我在控制台应用程序中有两个类。当实体不公开时,实体框架不会加载相关数据

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表示)在我的控制台应用程序(失败)。

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

     .... 
     } 

EDIT2 我有预感它似乎并没有被无论如何连接:

在我的ASP.NET MVC(正常工作)它被引用。

+0

您是否尝试过为订单添加'include'子句? –

+0

@PeterSmith我从来不用它们。在其他更大的项目(ASP.NET-MVC 5)中,我制作了超过10个模型类和数十个关联,启用了lazyloading并使用了虚拟关键字,而我从未遇到过这个问题。我应该在发布的代码中更改哪些内容?我不明白异常的原因,因为EF在我请求时会自动加载'order' - >这个代表延迟加载的想法。 – Yoda

+0

你是否检查过数据库中的内容?如果一个人已经存在,你的种子方法将添加一个具有空所有者的订单。这就是说,人。在这种情况下,订单应该是空的而不是空的。 –

回答

2

由于您的实体没有标记为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是空并且NRE被抛出。

+0

很棒的回答。如果我在ApplicationDbContext的构造函数中初始化Person.Orders,那么它也可以工作? – Yoda

+1

@Yoda,部分。您只需获得一个空的'List '(或'HashSet '),其中没有相关的“订单”。只有代理能够为您检测到这种关系,并将数据填入其中。有关更多信息,请参阅http://stackoverflow.com/a/20773057 – haim770

相关问题