2015-04-12 99 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

相關問題