53

Bowing to my Visual Studios request, I started my latest project using Entity Framework Core (1.0.1)

So writing my database models as I always have using the 'virtual' specifier to enable lazy loading for a List. Though when loading the parent table it appears that the child list never loads.

Parent Model

public class Events
{
    [Key]

    public int EventID { get; set; }
    public string EventName { get; set; }
    public virtual List<EventInclusions> EventInclusions { get; set; }
}

Child Model

public class EventInclusions
{
    [Key]
    public int EventIncSubID { get; set; }
    public string InclusionName { get; set; }
    public string InclusionDesc { get; set; }
    public Boolean InclusionActive { get; set; }

}

Adding new records to these tables seems to work as I am used to where I can nest the EventInclusions records as a List inside the Events record.

Though when I query this table

_context.Events.Where(e => e.EventName == "Test")

The Issue

EventInclusions will return a null value regardless of the data behind the scenes.

After reading a bit I am getting the feeling this is a change between EF6 which I normally use and EF Core

I could use some help in either making a blanket Lazy Loading on statement or figuring out the new format for specifying Lazy Loading.

Caz

6
  • Have you enabled lazy loading on the context? Commented Oct 19, 2016 at 4:33
  • 1
    Hey Gusman, I had never needed to in EF6 - I am guessing that might be in the issue because I have nothing pertaining to Lazy Loading in my context Commented Oct 19, 2016 at 4:35
  • If they've preserved the same mechanism (I still did not used EF with core) then you must set Configuration.LazyLoadingEnabled = true; and Configuration.ProxyCreationEnabled = true; on the context's constructor. Commented Oct 19, 2016 at 4:40
  • 3
    EF Core does not currently support automatic lazy loading Commented Oct 19, 2016 at 4:41
  • 3
    This is a good, but painful read... 100% regret the upgrade now! Commented Oct 19, 2016 at 4:49

7 Answers 7

41

Lazy loading is now available on EF Core 2.1 and here is link to the relevant docs:

https://learn.microsoft.com/en-us/ef/core/querying/related-data#lazy-loading

Sign up to request clarification or add additional context in comments.

5 Comments

Is there an easy way to generate the ef models for lazy loading? Because it requires the navigation properties to be virtual...
Never mind. I can update the models from the database and it generated the navigation properties virtual.
how do you turn it off?
@MelbourneDeveloper, My understasnding is that lazy loading is off by default. If you're wanting more data to be loaded, I use .Include() calls to load the nested data that I need as shown here: learn.microsoft.com/en-us/ef/core/querying/…
@huckjulius were you able to generate the virtual navigation properties using dotnet ef dbcontext scaffold ? It's removing the virtual keyword for me.
37

So it appears that EF Core does not currently support lazy loading. Its coming but may be a while off.

For now if anyone else comes across this problem and is struggling. Below is a demo of using Eager loading which is what for now you have to use.

Say before you had a person object and that object contained a List of Hats in another table.

Rather than writing

var person = _context.Person.Where(p=> p.id == id).ToList();

person.Hats.Where(h=> h.id == hat).ToList();

You need to write

var person = _context.Person.Include(p=> p.Hats).Where(p=> p.id == id).ToList();

And then person.Hats.Where(h=> h.id == hat).ToList(); will work

If you have multiple Lists - Chain the Includes

var person = _context.Person.Include(p=> p.Hats).Include(p=> p.Tickets)
                            .Include(p=> p.Smiles).Where(p=> p.id == id).ToList();

I kinda get why this method is safer, that your not loading huge data sets that could slow things down. But I hope they get Lazy loading back soon!!!

Caz

6 Comments

DO you have any idea how to implement repository pattern when I have to eager load the navigation properties? that is not easy at all when you have unknown number of include functions in need... any ideas?
@MohammedNoureldin I ran into the same problem. In the end I 'solved' it by simply exposing the IQueryable. e.g. I now have things like a IQueryable<T> GetByIdQueryable(string id) method on my repository. Callers can then do _repo.GetByIdQueryable(id) .Include(b => b.RelatedEntityProperty) .SingleOrDefault(); It works and is even okay with unit testing but to me it's a bit of a smell that you have to expose it this way. Another alternative would be to pass the string names of the properties you want to include but that's just asking for trouble imo.
And for multiple levels of includes ("also the Feathers on those Hats"), there is .ThenInclude()
the include seems to consume a lot of time for big table. Maybe just forget about lazyloading after all.
If Include is taking too much time, I would suggest looking at your database structure. If the DB is properly indexed and normalized it shouldn't be so bad.
|
33

you can instaling this package for enable lazy loading in EF Core 2.1.

Microsoft.EntityFrameworkCore.Proxies

and then set this config in your ef dbContext

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     => optionsBuilder
           .UseLazyLoadingProxies()
           .UseSqlServer("myConnectionString");

"Notice" this package works only on EF Core 2.1 and above.

Comments

12

For EF Core 2.1 and above,

Install:

 dotnet add package Microsoft.EntityFrameworkCore.Proxies --version 2.2.4 

Then Update your Startup.cs file as indicated below.

using Microsoft.EntityFrameworkCore.Proxies;



services.AddEntityFrameworkProxies();
services.AddDbContext<BlogDbContext>(options =>
            {
                options.UseSqlite(Configuration.GetSection("ConnectionStrings")["DefaultConnection"]);
                options.UseLazyLoadingProxies(true);
            });

2 Comments

This looked helpful so I tried it, but it doesn't work. I think that Lazy Loading cannot be turned off in EF Core: github.com/aspnet/EntityFrameworkCore/issues/15802
options.UseLazyLoadingProxies(false); disabled LazyLoading on my machine.
7

There's a pre-release version that just came out, regardless it's supposed to be available in full release soon.

A couple of caveats:

  • All your data properties that are more than simple types (ie: any other classes/tables) need to be public virtuals (default scaffolding they're not).
  • This line gets tucked into OnConfiguring on your data context:

        optionsBuilder.UseLazyLoadingProxies();
    
  • It's (currently) pre-release so may the force be with you.

Comments

5

LazyLoading is not yet supported by EF Core, but there is a non-official library that enables LazyLoading: https://github.com/darxis/EntityFramework.LazyLoading. You can use it until it is officially supported. It supports EF Core v1.1.1. It is available as a nuget package: https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.LazyLoading/

Disclaimer: I am the owner of this repo and invite you to try it out, report issues and/or contribute.

1 Comment

Please do something to support EF core 2.0
3

Lazy load is planned to be in EF core 2.1 - you can read more on why it is a must-have feature - here.

4 Comments

Link broken and when fixed requires login. Is there a publicly available source?
Link fixed :D Thanx for letting me know. Once the lazy load gets to EF7, it'll be usable...waiting for that for almost a year...
I tried it, and find it too slow, so it's better to skip the lazy loading after all. wildermuth.com/2018/07/28/Avoid-Lazy-Loading-in-ASP-NET
it's how you use it. lazy loading and n+1 select is a common issue. would avoid it if we know in advance what we need. the big issue with EF core before the support of lazy load was that it was not able to tell if you have a null value or just a non-loaded n:1 reference (missing proxy, no datanotloadedexception). it's like with bycicles, just because you use a car, does not mean someone other should not ever ride a bike.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.