EF:加载相关实体懒惰的方式不起作用
EF: Loading Related Entities Lazy way dont work
我哪里错了?我在导航 属性 Events
中收到 NullReferenceExeption
。它被标记为 virtual
并且 LazyLoadingEnabled
是明确允许的。
程序代码:
using (var db = new Db())
{
var person = new Person();
person.Name = "bla bla";
db.Persons.Add(person);
person.Events = new List<Event>(1);
person.Events.Add(new Event() { Description = "ABC", At = DateTime.Now });
db.SaveChanges();
}
using (var db = new Db())
{
var person = db.Persons.First();
Console.WriteLine(person.Events == null); //Output: True
Console.WriteLine(person.Events.Count); //System.NullReferenceException
}
显式加载有效:
var person = db.Persons.First();
db.Entry(person).Collection(p => p.Events).Load();
Console.WriteLine(person.Events == null); //Output: False
Console.WriteLine(person.Events.Count); //1
类结构:
class Db : DbContext
{
public Db()
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
Configuration.LazyLoadingEnabled = true;
}
public DbSet<Person> Persons { get; set; }
public DbSet<Event> Events { get; set; }
}
class Person
{
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
class Event
{
public int id { get; set; }
public DateTime At { get; set; }
public string Description { get; set; }
public Person Person { get; set; }
public int PersonId { get; set; }
}
很简单。
在 Person class 中创建默认构造函数并初始化 Events 集合,如
public Person()
{
Events = new HashSet<Event>();
}
并将类型为 Person 的虚拟 属性 添加到事件 class
编辑:
在 EF codefirst 中,您负责集合初始化,而 EF 负责从数据库中填充此集合
将 new Person()
替换为 context.Persons.Create()
。
这将为您提供 Entity Framework 个人代理,而不是 Person
。此代理 class 派生自 Person
,但其 Events
属性 已被延迟加载逻辑覆盖。
但是,这并不能解决您代码中的主要问题。这是上下文的重用。你不应该这样做。
您的模型 类 需要 public 才能延迟加载。将 class Person
和 class Event
更改为 public class Person
等,您的测试程序将开始工作。
您的代码没有任何问题:如果您对空集合执行 Count
,您将始终得到 NullReferenceException
- 这与 Entity Framework 无关,那是 .NET .
null 集合和空集合是有区别的。
现在,如果您想避免此类 NullReferenceException
异常,您始终可以在默认构造函数中启动列表,如:
class Person
{
public Person()
{
Events = new List<Event>();
}
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
public class Person
{
public Person()
{
Events = new List<Event>();
}
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
public class Event
{
public int id { get; set; }
public DateTime At { get; set; }
public string Description { get; set; }
public Person Person { get; set; }
public int PersonId { get; set; }
}
您需要使用相同类型的集合来初始化任何集合导航属性,而不是 'HashSet',就像这样。
我哪里错了?我在导航 属性 Events
中收到 NullReferenceExeption
。它被标记为 virtual
并且 LazyLoadingEnabled
是明确允许的。
程序代码:
using (var db = new Db())
{
var person = new Person();
person.Name = "bla bla";
db.Persons.Add(person);
person.Events = new List<Event>(1);
person.Events.Add(new Event() { Description = "ABC", At = DateTime.Now });
db.SaveChanges();
}
using (var db = new Db())
{
var person = db.Persons.First();
Console.WriteLine(person.Events == null); //Output: True
Console.WriteLine(person.Events.Count); //System.NullReferenceException
}
显式加载有效:
var person = db.Persons.First();
db.Entry(person).Collection(p => p.Events).Load();
Console.WriteLine(person.Events == null); //Output: False
Console.WriteLine(person.Events.Count); //1
类结构:
class Db : DbContext
{
public Db()
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
Configuration.LazyLoadingEnabled = true;
}
public DbSet<Person> Persons { get; set; }
public DbSet<Event> Events { get; set; }
}
class Person
{
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
class Event
{
public int id { get; set; }
public DateTime At { get; set; }
public string Description { get; set; }
public Person Person { get; set; }
public int PersonId { get; set; }
}
很简单。
在 Person class 中创建默认构造函数并初始化 Events 集合,如
public Person()
{
Events = new HashSet<Event>();
}
并将类型为 Person 的虚拟 属性 添加到事件 class
编辑: 在 EF codefirst 中,您负责集合初始化,而 EF 负责从数据库中填充此集合
将 new Person()
替换为 context.Persons.Create()
。
这将为您提供 Entity Framework 个人代理,而不是 Person
。此代理 class 派生自 Person
,但其 Events
属性 已被延迟加载逻辑覆盖。
但是,这并不能解决您代码中的主要问题。这是上下文的重用。你不应该这样做。
您的模型 类 需要 public 才能延迟加载。将 class Person
和 class Event
更改为 public class Person
等,您的测试程序将开始工作。
您的代码没有任何问题:如果您对空集合执行 Count
,您将始终得到 NullReferenceException
- 这与 Entity Framework 无关,那是 .NET .
null 集合和空集合是有区别的。
现在,如果您想避免此类 NullReferenceException
异常,您始终可以在默认构造函数中启动列表,如:
class Person
{
public Person()
{
Events = new List<Event>();
}
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
public class Person
{
public Person()
{
Events = new List<Event>();
}
public int id { get; set; }
public string Name { get; set; }
public virtual List<Event> Events { get; set; }
}
public class Event
{
public int id { get; set; }
public DateTime At { get; set; }
public string Description { get; set; }
public Person Person { get; set; }
public int PersonId { get; set; }
}
您需要使用相同类型的集合来初始化任何集合导航属性,而不是 'HashSet',就像这样。