[英]Loading of Lazy collections in entity framework too lazy
我遇到的问题是实体框架没有正确处理我用几个对象手动初始化的集合。
我正在使用基于使用私有字段来支持公共集合属性的众多示例中的任何代码。 例如,根据这个问题
但是,如果我后者想要将此字段与LINQ查询一起使用,那么我遇到了问题。
我的模型结构如下。
public abstract class Parent
{
[Key]
public int Id { get; set; }
public virtual List<Child> Childeren
...
}
public abstract class Child
{
[Key]
public int Id { get; set; }
protected List<Grandchild> _grandchilderen;
public virtual List<Grandchild> Grandchilderen
{
get
{
if (_grandchilderen== null)
SpawnGrandchilderen();
return _grandchilderen;
}
set { _grandchilderen= value; }
}
private void SpawnGrandchilderen(){
_grandchilderen=new List<Grandchild>(){new Grandchild(), new Grandchild()};
}
...
}
public abstract class Child
{
[Key]
public int Id { get; set; }
...
}
如果我使用像这样的查询
parent_instance.Childeren.SelectMany(C=>C.Grandchilderen).ToList()
每个孩子都会调用SpawnGrandchilderen()来覆盖应该从数据库加载的数据。
如果我在getter的开头放置一个断点,我可以看到_grandchilderen总是为null。
如果我在linq查询之前放置一个断点并在继续执行之前使用监视窗口手动探索childeren,我能够使代码按预期工作。
我认为这是一个与延迟加载有关的问题,但我不确定如何有效地解决这个问题。
编辑:我已经做了一些更多的探索,我发现的是:
首次访问时,Grandchilderen列表始终为空。
如果我用_grandchilderen = new List<Grandchild>()
替换调用SpawnGrandchilderen()
并_grandchilderen = new List<Grandchild>()
放置一个断点,我可以看到该行正被命中,但是当我预期空的时候我的数据实际返回了要返回的数组。
但是,如果我更换线路
_grandchilderen = new List<Grandchild>(){new Grandchild()};
然后getter返回的值不包含我的数据库数据,但包含我新创建的孙子。
某种奇怪的EF伏都教正在这里,我不知道如何解决它。
我设法根据grek40的提示自己解决了这个问题,我通过确保第一次调用函数而不修改值来完成工作。 (来自非EF代码)以确保通过正确链接。
通过将我的类修改为以下函数
private bool _grandchilderenloaded = false;
protected List<Grandchild> _grandchilderen;
public virtual List<Grandchild> Grandchilderen
{
get
{
if (!_grandchilderenreloaded)
{
_grandchilderenreloaded = true;
if (Grandchilderen == null) // Note this getter calling itself here is where the magic happens
SpawnGrandchilderen(); // The Db value has now been loaded, if it was non null do some setup.
}
return _grandchilderen;
}
set { _grandchilderen= value; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.