Entity Framework not loading reference and collection properties lazily
I have Backpack and Book objects. Backpack book links (one to many). I am creating a copy of a backpack and a bunch of books. So in this case, the backpack has a bunch of books. I am saving these objects to db. I check that they were saved in db. When I try to load the backpack, it loads fine and all properties are set except for the navigation properties. I also check that LazyLoading is not disabled. My navigation properties have the virtual keyword. I'm not sure what I am doing wrong. If I try to load the backpack using Include (), it loads the books:
dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()
I'm trying to figure out why it doesn't load books lazily? I have the same problem downloading a book. When I download the book, it doesn't have the included backpack. I see the BackpackId is there.
In my getter / setter function, I have some logic that will run, but I don't know how that might be the problem.
source to share
After days of debugging, finally figured out the problem. As mentioned above, you must enable LazyLoading and ProxyCreating. I had problems even after enabling LazyLoading and ProxyCreating. Also make sure you specify your navigation properties as virtual
, otherwise EF won't be able to load objects lazily.
So the problem was that EF was not breaking Proxies due to my object not having a public or protected NO parameterless constructor. After creating a public (in my case protected) constructor with no parameter, it worked.
NOTE. Lack of a public / protected constructor without parameters will not affect heavy load.
Here is a link that explains the requirements for LazyLoading
source to share
With limited information, I see the following explanations for your problem.
Lazy Loading or Proxy Creation Disabled
Make sure lazy loading and proxy creation is enabled, the former won't work without the latter.
dbContext.Configuration.ProxyCreationEnabled = true;
dbContext.Configuration.LazyLoadingEnabled = true;
Accessing Objects After Deleting Context
Simplified, Lazy Loading works like this:
- Whenever you retrieve an entity from context, you actually end up with an auto-generated subclass of the class you expected, which overrides your navigation properties
virtual
, which is a proxy . - Whenever you access the specified navigation properties, the proxy will access the database and load related objects when needed.
This last step is, of course, only possible if the object / proxy is still attached to the context and therefore can query the database to retrieve the specified objects.
using( var dbContext = new MyContext() )
{
dbContext.Configuration.ProxyCreationEnabled = true;
dbContext.Configuration.LazyLoadingEnabled = true;
// Note: You can modify or derive from `MyContext` so that this is
// done automatically whenever a new `MyContext` is instantiated
var backpack = dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault();
// This should work
var firstBook = backpack.Books.FirstOrDefault();
}
// This will probably not, because the context was already disposed
var firstDrink = backpack.Drinks.FirstOrDefault();
I hope this helps, but feel free to provide more information if it is not
source to share
The desired download is achieved using the method Include()
, and as a result, you force the download to be loaded using Include("Books")
.
Change this:
dbContext.Backpacks.Where(b=>b.Name!="").Include("Books").FirstOrDefault()
:
dbContext.Backpacks.Where(b=>b.Name!="").FirstOrDefault()
You should now see what Books
no longer looks like loading.
Reference:
source to share