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. e.g. as per this question
However I am running into issues if I latter want to use this field with LINQ queries.
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.
If I place a breakpoint at the start of the getter, I can see that _grandchilderen is always 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.
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.
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.
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.
Some kind of weird EF voodoo is going on here and I am not sure how to troubleshoot it.