6

Consider following entity model:

public class Parent
{
    public virtual FirstChild FirstChild { get; set; }
    public virtual SecondChild SecondChild { get; set; }
}

In my code, I have loaded Parent entity:

Parent parent = <loaded in some way>;

To explicitly load its navigational properties, I use

db.Entry(parent).Reference(p => p.FirstChild).Load();
db.Entry(parent).Reference(p => p.SecondChild).Load();

But this results in two DB queries.

Question: is there a more elegant way, that would allow to explicitly load more than one navigational property in single query?

If I didn't have parent loaded, I would do eager loading:

Parent parent = db.Parents
    .Include(p => p.FirstChild)
    .Include(p => p.SecondChild)
    .FirstOrDefault();

but, as I mentioned, I already have it loaded without related entities (and I can't modify the loading code).

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
lxa
  • 3,234
  • 2
  • 30
  • 31
  • 1
    How would you load it with one query in SQL? It seems to me that you would have to load the parent again in order to connect the navigational properties. If you are OK with a batch load instead, I think you can use `Future` from [EntityFramework.Extended](https://github.com/loresoft/EntityFramework.Extended). – default Mar 12 '15 at 15:49
  • @RazvanDumitru because this question is related to "lazy loading" feature of Entity Framework – lxa Mar 12 '15 at 16:57
  • @Default SQL - single query on parent table with two joins for both children; suggested `Future()` is nice - though it would still result in two separate queries, as far as I get it? – lxa Mar 12 '15 at 16:57
  • yes, I think so too, but it would still be one call to the database. To be honest, I haven't tested it and I'm not that familiar with how batches are made :) - If you still need the parent table, wouldn't you be able to simply to override the `parent` entity you have with a fresh one from the database? Since you still need to go via the parent table, it seems the easiest way. Any limitations there? – default Mar 12 '15 at 17:13

1 Answers1

1

The only possible way (afaik) is to reload the parent property. Assuming the variable parent is attached to the context:

var tmp = db.Parents
    .Include(p => p.FirstChild)
    .Include(p => p.SecondChild)
    .FirstOrDefault(p => p.Equals(parent));

// tmp and parent are the same instance now!
var isTrue = ReferenceEquals(tmp, parent);

var child1 = parent.FirstChild;  // is already loaded
var child2 = parent.SecondChild; // is already loaded

This works, because the context will detect that entity you are looking for is loaded and attached already and therefore not create a new one but rather update the old one (parent in this case).

Tim Pohlmann
  • 4,140
  • 3
  • 32
  • 61