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 将无法为实体类型生成代理。
查看 EntityProxyFactory
的 source 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。
我在控制台应用程序中有两个 类。
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 将无法为实体类型生成代理。
查看 EntityProxyFactory
的 source 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。