0

I have an EF Core 2.1 Code First model with a "parent-child" type relationship between two classes:

class Parent
{
    public int Id {get; set;}
    public string Name {get; set;}
}

class Child
{
    public int Id {get; set;}
    public string Description { get; set; }
    public Parent Parent { get; set; }
}

I want to load a certain Parent, and make sure that all its Child entities are loaded too. However, there is no navigation property to Child, and I cannot modify the classes, so I can't add one.

dbContext.Parents
    .Include(p => p.???)
    .Find(1);

I suppose I could do a second query where I look everything up in reverse:

dbContext.Children.Where(c => c.Parent.Id == loadedParent.Id)

but that does not seem very efficient, especially when you load multiple parents and do something horrible like this:

var parentIds = loadedParents.Select(p => p.Id);
var children = dbContext.Children.Where(c => parentIds.Contains(c.Parent.Id));

Is there a way to make sure entities are loaded when you only have a "child-to-parent" navigation property?

Bas
  • 1,946
  • 21
  • 38

1 Answers1

1

make sure that all its Child entities are loaded too

So load the Child entities:

var children = dbContext.Children.Include(c => c.Parent)
    .Where(c => c.Parent.Id == 1).ToList();

Or use wider selection criteria than c.Parent.Id == 1 if you want to get multiple parents.

If necessary you can list the loaded parents by accessing the Local collection:

va parents = dbContext.Parents.Local;
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
  • Is that really the most efficient way to do it? It seems like the database query would get exponentially more complicated pretty soon. – Bas Nov 05 '18 at 21:48
  • 1
    As for efficiency, the generated SQL will be almost identical to a query that does have `parent.Children`. As for complexity, there's a predicate `Where(c => c.Parent ...)` in stead of `Where(p => p ...)`. I don't see how this complexity could grow exponentially. The only difference (compared to including children) is that you won't get parents that have no children. If that's a problem you should use GroupJoin (the LINQ equivalent of outer join). – Gert Arnold Nov 05 '18 at 22:08
  • What's the most efficient way to do this with multiple parent ids? Is it Where(c => parentIds.Contains(c.Id) or is there a method that generates better SQL? – Bas Nov 06 '18 at 08:10
  • 1
    `Contains` is fine when `parentIds` isn't too long (several thousands). If it is, you could try [this](https://stackoverflow.com/q/24534217/861716). – Gert Arnold Nov 06 '18 at 08:16