0

Scenario:

public class A{
    public B InstanceOfB { get; set; }
}

public class B{
    public string Name { get; set; }
    public virtual ICollection<A> ListOfA { get; set; }
}

public void Boo(){
   using (var db = new myContext()){
       var instanceOfA = db.A.Find(1);
       db.Entry(instanceOfA).Reference(a => a.InstanceOfB).Load();
   }
}

In my dbcontext I turned off ProxyCreationEnabled and turned on LazyLoadingEnabled.

When I use Load the reference of property ListOfA is loaded too and it's recursive.

How can I prevent this behavior ?

Felippe Tadeu
  • 237
  • 2
  • 11
  • How do you know it's loaded? Do you observe SQL statements being executed to load it? Since you have LazyLoadingEnabled, any attempt to inspect ListOfA, even in the debugger, will trigger lazy loading of the collection if `db` is still in scope. If `db` is not in scope, you'll get an exception. – Eric J. Oct 17 '18 at 16:41
  • @EricJ. Understood, when I put the cursor mouse in the instanceOfA and expand the property InstanceOfB and the ListOfA and an item of the list aways is loading,I'm correct ? – Felippe Tadeu Oct 17 '18 at 16:46
  • Exactly, when you inspect the value in the debugger, you trigger loading. It's easy to track what SQL commands are actually issued. See this https://stackoverflow.com/questions/16880687/how-can-i-log-the-generated-sql-from-dbcontext-savechanges-in-my-program – Eric J. Oct 17 '18 at 16:53

1 Answers1

1

In your scenario, lazy loading is enabled. Any attempt to inspect ListOfA will cause EF to attempt to lazy load that collection. If db is still in scope, it will load (if not, you'll get an exception).

You indicated in the comments that you're inspecting the value in the debugger, so that is what's triggering the load.

You can easily watch the SQL commands as they are issued, observing the initial load and subsequent lazy load when you inspect the collection. See

How can I log the generated SQL from DbContext.SaveChanges() in my Program?

If you want to ensure that the child collection is always loaded, even after the object leaves scope of db, you can do something like:

using System.Data.Entity; // Needed for the delegate form of .Include(...)

using (var db = new myContext())
{
    var instanceOfA = db.A
        .Include(a => a.InstanceOfB)
        .Include(a => a.InstanceOfB.ListOfA)
        .First(); // Or .Where(...) depending on needs
}
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • I don't know if i can ask one thing more but, when I tried to return all the result in a method like `public IHttpActionResult` and return using `Ok()` then relations are loaded too ? – Felippe Tadeu Oct 17 '18 at 17:08
  • Once your object leaves scope of `db`, any further attempt to access not-yet-loaded properties will throw an exception because the connection to the database is lost. If you want to ensure that the collection is always loaded, you can use the Include() method. I'll update the answer with an example of that. – Eric J. Oct 17 '18 at 17:13
  • 1
    Thank for your responses! Have a nice day. – Felippe Tadeu Oct 17 '18 at 17:17