Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule-based eager load (Include) (load patterns/LoadWith) #2953

Open
Tracked by #22954
Grinderofl opened this issue Aug 28, 2015 · 22 comments
Open
Tracked by #22954

Rule-based eager load (Include) (load patterns/LoadWith) #2953

Grinderofl opened this issue Aug 28, 2015 · 22 comments

Comments

@Grinderofl
Copy link
Contributor

Grinderofl commented Aug 28, 2015

Proposal here: #2953 (comment)
First part of proposal has been split off in #21540 and implemented in 5.0 release.


Currently, in no version of EF, do we have a way of specifying, that whenever we ask for a specific entity, we also want some related entities loaded, too, having to use .Include() in every select. This increases verbosity and the amount of code required, when it could be avoided. I understand that it was never feasible to consider for EF < 7, but I feel should be considered now, to bring the library more in line functionality-wise to another popular ORM.

I've been fiddling with annotations a little to try to see if I can get it to work, but haven't spent a lot of time on it, maybe there's a better way? Either way, for syntax, I propose adding to ReferenceCollectionBuilder method Include(bool lazy = true) (this would follow path where a convention that automatically includes all lazy properties of type, but on individual entities you could re-enable lazy.

@rowanmiller rowanmiller changed the title Add support for lazy include Rule-based eager load (include) Sep 1, 2015
@rowanmiller
Copy link
Contributor

This is somewhat covered by #1985 but it is also a smaller feature within that larger one. Leaving active and moving to backlog since we won't do this for the initial release but it would be good to enable.

@AndriySvyryd
Copy link
Member

Clearing the milestone as this would be nice for owned entities

@ajcvickers ajcvickers added this to the 2.0.0 milestone Apr 14, 2017
@ajcvickers
Copy link
Member

@anpete just to do the convention part of this for owned entity types (i.e. those that are known to be part of an aggregate)

@ajcvickers
Copy link
Member

Note: when this is implemented, consider whether the API created could be used with ad-hoc Includes as described in #4490, and/or whether the need for a an API like that described in #4490 is something that is still needed.

@ajcvickers
Copy link
Member

See also #12238

@optiks
Copy link

optiks commented Jul 25, 2018

We needed to do this in order to mimic LINQ to SQL's global LoadWith<> behaviour. We code-gened the includes, including when querying through a base type. Awesome work on including "Include on derived types" team!

@ajcvickers ajcvickers changed the title Rule-based eager load (include) Rule-based eager load (Include) (load patterns/LoadWith) Dec 17, 2018
@ajcvickers ajcvickers removed this from the Backlog milestone Dec 17, 2018
@AndriySvyryd
Copy link
Member

@mhDuke Since we now have a design it's possible this will be done this year.

@ilmax
Copy link
Contributor

ilmax commented Jan 9, 2020

@AndriySvyryd just to double check, this will allow us to define loading rules at model level i.e. something like this:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Order>().LoadWith(o => o.LineItems);
}

And will also allow us to opt-out at query level i.e.

var orderWithoutLineItems = context.Orders.IgnoreLoadWith().SingleOrDefault(o => o.Id == OrderId);

In this case the IgnoreLoadWith will only opt-out the LineItems navigation property while still eager load all (eventually) configured owned entities

@AndriySvyryd
Copy link
Member

@ilmax Something like that

@vflame
Copy link

vflame commented May 30, 2020

We're running into this limitation frequently as we upgrade our codebase to use generics. We should be able to delegate the loading behavior to the concrete type at runtime. For example:

public abstract class PurchaseOrderBase
{
    public abstract decimal CalculateTotal();
}

public class FixedPricePurchaseOrder() : PurchaseOrderBase
{
    public override decimal CalculateTotal()
    {
        return 50;
    }
}

public class ProratedPurchaseOrder() : PurchaseOrderBase
{
    private ProrationData _prorationData;

    public override decimal CalculateTotal()
    {
        return _prorationData.CalculateProration();
    }
}

Currently, we do the following:

GetPurchaseOrder<IEnumerable<T>>() where T : PurchaseOrderBase
{
    return _context.Set<PurchaseOrderBase>()
    .Include("_prorationData").ToList();
}

But it would be ideal to map it in the EF configuration. We can't use owned types because the proration data isn't a value object but we want it to be eagerly loaded by default.

This really hampers our ability to make use of generics. Is there a better workaround for this than just Include with strings in the meantime?

@smitpatel
Copy link
Member

Splitting off first part of #2953 (comment) which is model based configuration. Filed #21540 which is happening in 5.0.
LoadWith API and similar pattern are still in backlog and we consider it in our release planning for next release.

@ajcvickers
Copy link
Member

See also proposal here: #23110 (comment)

@yecril71pl
Copy link
Contributor

Please clarify whether it is about making in-class navigations (as opposed to in-context navigations) easier to configure. You can call Include on a DbSet but not on an in-owner ICollection. Of course, you can always inject AsQueryable but that is a mouthful. I also wonder whether it would be advantageous to simply define an in-owner navigation as an IQueryable instead (and whether it would work at all).

@mhDuke
Copy link

mhDuke commented Jan 31, 2022

in december 2019. I filed a feature request #19301 to forcefully eager load some navigation. which turns to be duplicate of this issue. I was fairly new to ef core and I was rigid. Now after am a bit more mature, as a developer and user of ef core, I no longer see the need for such feature. Not only to always include a navigation property is not needed, but it is potentially dangerous for performance. It's always best to use IQueryable.Select() to carefully craft the object with only properties and navigations required for the application use case. If I forgot a required navigation, an exception will be thrown a property is null. Not initializing (ctor() { NavigationCollection = new NavigationCollection() }) is key to spot a missing Include().
That said there could be use cases that prove me wrong.

@boukeversteegh
Copy link

For those ending up here looking for a way to Auto Include / include by default in Entity Framework 6, here's how to do it:

public static void Build(ModelBuilder modelBuilder) {
    modelBuilder.Entity<Post>().Navigation(p => p.author).AutoInclude()
}

https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager#model-configuration-for-auto-including-navigations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment