Eager , Lazy and Explicit Loading in Ef6

Eager , Lazy and explicit loading in EF6

If this small resume is true ?

Yes.

If it is true, what is the difference between eager and explicit loading?

Eager loading is the opposite of Lazy loading but Explicit loading is similar to lazy loading, except that: you explicitly retrieve the related data in code; it doesn't happen automatically when you access a navigation property. You load related data manually by getting the object state manager entry for an entity and calling the Collection.Load method for collections or the Reference.Load method for properties that hold a single entity.

From techblog:

Eager Loading :

Eager loading is the opposite of Lazy loading which is : The process
of loading a specific set of related objects along with the objects
that were explicitly requested in the query.

Explicit Loading :

Explicit loading is defined as : when objects are returned by a query,
related objects are not loaded at the same time. By default, they are
not loaded until explicitly requested using the Load method on a
navigation property.

And:

If I Use lazy loading and I call for example dpc_gestion.dpc_participant, does the navigation properties loads?or I will get an exception?

You don't get any exception and the navigation properties should loads.

Is there a case when eager loading or explicit loading were better
than lazy loading in performance and responsiveness?

Eager loading is typically more efficient when you need the related data for all retrieved rows of the primary table. And also when relations are not too much, eager loading will be good practice to reduce further queries on server. But when you know that you will not need a property instantly then lazy loading maybe a good choice. And also eager loading is a good choice in a situation where your db context would be disposed and lazy loading could not take place anymore. For example consider the following:

public List<Auction> GetAuctions()
{
using (DataContext db = new DataContext())
{
return db.Auctions.ToList();
}
}

After calling this method, You cannot load the related entity lazily because the db is disposed and so the Eager Loading would be a better choice here.

One more thing to note is: Lazy loading will produce several SQL request while Eager loading load data with one request. Eager loading is also a good choice to solve the n+1 selects issue in ORMs.
Have a look at this post: What is the n+1 selects issue?

differences between Eager Loading and Explicit Loading

Eager loading loads related entities as part of the query, i.e. the enties are loaded when the query is actually executed. This is the opposite of lazy loading where the related entities are loaded when you access them through a navigation property.

Calling Load() explicitly loads the entities on your request instead of waiting for you to access the navigation properties. It's for example useful when the initial query doesn't return any related entities (because you didn't use eager loading) and you have disabled lazy loading for whatever reason.

Combining lazy and eager loading in EF

Yes you can do that.And it's a Good practise too according to the real situation like yours.

When you don't need the Lazyloding ,on that particular method you can disable it as shown below.

public List<PropertyListDto> SearchProperties(AdditionalSearchInput input)
{
_context.Configuration.LazyLoadingEnabled = false;//to remove lazy loading

///your code
}

Note : In Entity Framework 4 and beyond Lazy Loading is enabled by default. We can disable it globally, on DbContext level, or selectively, on query level as shown above.

Here is how to do it on DbContext level.

public partial class MyDBEntities : DbContext
{
public MyDBEntities(): base("name=MyDBEntities")
{
this.Configuration.LazyLoadingEnabled = false;
}
}

Update : The 50 controllers where you don't need lazyloding you can disable it on constractor level as shown below.Then you don't need to give it on query level on each method.I think it's very quick way to implement it :)

public class YourAppService : IYourAppService
{
private readonly YourDbContext _context;

public YourAppService(YourDbContext context)
{
_context = context;
_context.Configuration.LazyLoadingEnabled = false;//to remove lazy loading
}
}

Is projecting lazy, eager or explicit in entity framework?

Lazy loading, eager loading and explicit loading works in the most common scenarios. Projection is replacement for eager loading because it can also load related entities with single query. Using projection make sense if you need to load entities with some complex query because eager loading doesn't work in these cases. Use projection if you need:

  • Any kind of join or aggregation in the linq query. As I know Include is ignored once you start using manual joins.
  • Any kind of filtering or sorting in navigation property. Include can only load all related entities from navigation property without any sorting. Once you need to apply any where condition or order by on related entities you can't use Include and you must use projection.

Lazy Loading vs Eager Loading

I think it is good to categorize relations like this

When to use eager loading

  1. In "one side" of one-to-many relations that you sure are used every where with main entity. like User property of an Article. Category property of a Product.
  2. Generally When relations are not too much and eager loading will be good practice to reduce further queries on server.

When to use lazy loading

  1. Almost on every "collection side" of one-to-many relations. like Articles of User or Products of a Category
  2. You exactly know that you will not need a property instantly.

Note: like Transcendent said there may be disposal problem with lazy loading.

EF Core is lazy loading when I try to eager load with .Include()

Ok, after investigating the issue, there is a problem with EF Core 2.x lazy loading via proxies implementation. The related tracked issues are

  • #15170: Eager loading include with using UseLazyLoadingProxies
  • #12780: Store IsLoaded flags in proxy for better lazy-loading experience

The problem is that the navigation properties are eager loaded, but LazyLoader does not know that when disposed - can't safely access context change tracker and simply is throwing exception. The relevant code can be seen here, in the very first line:

if (_disposed)
{
Logger.LazyLoadOnDisposedContextWarning(Context, entity, navigationName);
}

As I read it, it's supposed to be fixed in EF Core 3.0 when released with the following "breaking change" - Lazy-loading proxies no longer assume navigation properties are fully loaded. It also partially explains the current problem:

Old behavior

Before EF Core 3.0, once a DbContext was disposed there was no way of knowing if a given navigation property on an entity obtained from that context was fully loaded or not.

Unfortunately this doesn't help you with the current problem. The options I see are:

  1. Wait for EF Core 3.0 release
  2. Don't use lazy loading via proxies
  3. Turn off the lazy loading on disposed context warning - by default it is Throw, change it to Log or Ignore, for instance:

    optionsBuilder.ConfigureWarnings(warnings => warnings
    .Log(CoreEventId.LazyLoadOnDisposedContextWarning)
    );

Coming from SQL to EF6 Which loading method should I start with? Lazy Loading, Explicit loading, Eager loading

My experience: I started with lazy loading as a beginner, then started to use Include when perf became unacceptable. Now I almost always write queries manually because I outgrew Include as well. The more performance matters to you the less convenience you can have. The more complex and demanding a code-base become the more you're forced to take control.

Often, lazy loading is fine one moment and the next moment you need to do manual querying and rip out all lazy loading stuff. The transition is often sudden and radical. Example: you render a list of questions on a page. Now, you also want to show question.Answers.Count() for each question. Lazy loading cannot do that. Now you need to introduce a custom view model and a custom query (questions.Select(q => new { q.ID, q.Title, AnswerCount = q.Answers.Count() })). This always happens sooner or later, triggered by increasing business requirements. I usually go directly with the manual query.

To clarify, there is no well-performing way to solve the example I just gave, except with a custom query. If you didn't query when developing the first version of the project, you might have to tell the customer that this little change (just the added answer count) will cost a lot of money because you now have to rewrite some parts of the page. Inflexibility tends to be costly later.

Also, see the comments under the question for further context.

Lazy and Eager Loading in Entity Framework gives same result while using .Include() in both?

When you're explicitly using Include(), you're preforming an Eager Loading. Obviously, disabling/enabling Lazy Loading has no effect.

The difference will be reflected when you'll omit the Include and try to access the Products navigation-property in some of your Category instances. When Lazy-Loading is enabled, EF will load it from the database. When it's disabled, you'll get null.



Related Topics



Leave a reply



Submit