简体   繁体   English

在实体框架中加载Lazy集合太懒了

[英]Loading of Lazy collections in entity framework too lazy

I am having issues with entity framework not properly handling collections that I manually initialize with a few objects. 我遇到的问题是实体框架没有正确处理我用几个对象手动初始化的集合。

I am using code based off any of the numerous examples of using a private field to back a public collection property. 我正在使用基于使用私有字段来支持公共集合属性的众多示例中的任何代码。 eg as per this question 例如,根据这个问题

However I am running into issues if I latter want to use this field with LINQ queries. 但是,如果我后者想要将此字段与LINQ查询一起使用,那么我遇到了问题。

My model structure is as follows. 我的模型结构如下。

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; }

    ...
}

If I use a query like 如果我使用像这样的查询

parent_instance.Childeren.SelectMany(C=>C.Grandchilderen).ToList()

SpawnGrandchilderen() is called on every child overwriting data that should have been loaded from the database. 每个孩子都会调用SpawnGrandchilderen()来覆盖应该从数据库加载的数据。

If I place a breakpoint at the start of the getter, I can see that _grandchilderen is always null. 如果我在getter的开头放置一个断点,我可以看到_grandchilderen总是为null。

I am able to get the code to work as expected if I place a breakpoint before the linq query and manually explore childeren using the watch window before continuing execution. 如果我在linq查询之前放置一个断点并在继续执行之前使用监视窗口手动探索childeren,我能够使代码按预期工作。

I believe this is an issue to do with lazy-loading but I am not sure how to go about solving this issue efficiently. 我认为这是一个与延迟加载有关的问题,但我不确定如何有效地解决这个问题。


Edit: I have done a bit more poking around and all I have found is: 编辑:我已经做了一些更多的探索,我发现的是:

When it is first accessed the Grandchilderen list is ALWAYS null. 首次访问时,Grandchilderen列表始终为空。

If I replace the call SpawnGrandchilderen() with _grandchilderen = new List<Grandchild>() and put a breakpoint on the line I can see that the line is being hit and yet my data from the database is actually returned when I would expect an empty array to be returned. 如果我用_grandchilderen = new List<Grandchild>()替换调用SpawnGrandchilderen()_grandchilderen = new List<Grandchild>()放置一个断点,我可以看到该行正被命中,但是当我预期空的时候我的数据实际返回了要返回的数组。

However if I replace the line with 但是,如果我更换线路

_grandchilderen = new List<Grandchild>(){new Grandchild()};

Then the value returned from the getter contains none of my database data, but does include my newly created grandchild. 然后getter返回的值不包含我的数据库数据,但包含我新创建的孙子。

Some kind of weird EF voodoo is going on here and I am not sure how to troubleshoot it. 某种奇怪的EF伏都教正在这里,我不知道如何解决它。

I managed to solve this myself based on the hints from grek40 I was able to get things working by ensuring that the first call to the function finishes without modification to the value. 我设法根据grek40的提示自己解决了这个问题,我通过确保第一次调用函数而不修改值来完成工作。 (from non EF code) to ensure things get linked through properly. (来自非EF代码)以确保通过正确链接。

by modifying my class to the following function 通过将我的类修改为以下函数

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM