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

Support filtered Include #1833

Open
0xdeafcafe opened this Issue Mar 16, 2015 · 107 comments

Comments

Projects
None yet
@0xdeafcafe
Contributor

0xdeafcafe commented Mar 16, 2015

We keep this issue to track specifying filters inline when you specify eager loading in a query. However there are many scenarios that can be satisfied with global query filters:

Please learn about global query filters

We are seeing that a large portion of the scenarios customers want this feature for can already be better addressed using global query filters. Please try to understand that feature before you add your vote to this issue.

We are keeping this issue open only to represent the ability to specify filters on Include on a per-query basis, which we understand can be convenient on some cases.

Original issue:

Doing a .Where() inside a .Include() is allowed (by the syntax, it fails in execution). However, if you then follow that up with a .ThenInclude(), like so:

.Include(t => t.Ratings.Where(r => !r.IsDeleted))
.ThenInclude(r => r.User)

You get the following error:

'IEnumerable' does not contain a definition for 'User' and no extension method 'User' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

Is this something you're aware of and going to allow in a future version, or am I just doing something wrong and It's already supported?

@popcatalin81

This comment has been minimized.

Show comment
Hide comment
@popcatalin81

popcatalin81 Mar 16, 2015

Historically this was not supported by EF, However this would be a nice feature to have. We had to implement something similar ourselves in the our code base using Linq tree rewriting. It hope the EF team considers this.

Historically this was not supported by EF, However this would be a nice feature to have. We had to implement something similar ourselves in the our code base using Linq tree rewriting. It hope the EF team considers this.

@0xdeafcafe

This comment has been minimized.

Show comment
Hide comment
@0xdeafcafe

0xdeafcafe Mar 16, 2015

Contributor

Yeah. I noticed discussion of this in the .Include() design meeting docs. It looked as if it was road-mapped and going to be implemented. Although that could all just be a dreadful fantasy and I'm completely wrong.

Contributor

0xdeafcafe commented Mar 16, 2015

Yeah. I noticed discussion of this in the .Include() design meeting docs. It looked as if it was road-mapped and going to be implemented. Although that could all just be a dreadful fantasy and I'm completely wrong.

@rowanmiller rowanmiller added this to the Backlog milestone Mar 23, 2015

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Mar 23, 2015

Member

Moving to back log as a new feature (we do want to support filtered include but it is a lower priority than some other features that were available in EF6).

Member

rowanmiller commented Mar 23, 2015

Moving to back log as a new feature (we do want to support filtered include but it is a lower priority than some other features that were available in EF6).

@rowanmiller rowanmiller changed the title from Can't do a Where statement inside an Include, if it's followed by another Include to Support filtered Include Mar 23, 2015

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Mar 23, 2015

Member

Opened new issue for better exception message #1883

Member

rowanmiller commented Mar 23, 2015

Opened new issue for better exception message #1883

@mikes-gh

This comment has been minimized.

Show comment
Hide comment
@mikes-gh

mikes-gh Dec 12, 2015

Don't underestimate the value of filtered include. It was a top request in ef 6.
I came across this requirement on my first ef 7 project.
I'd take that over lazy loading any day.

Don't underestimate the value of filtered include. It was a top request in ef 6.
I came across this requirement on my first ef 7 project.
I'd take that over lazy loading any day.

@rendmath

This comment has been minimized.

Show comment
Hide comment
@rendmath

rendmath Dec 30, 2015

Any non-trivial development using the Entity Framework will encounter this limitation.

It also has consequences on other technologies likes the OData protocol, because there is really no point to adding filtered $expands to the protocol if EF does not support them.

For those who are not (yet) familiar with the internals of EF Core, could you point us to the parts of the Entity Framework that would be impacted in order support this ?

rendmath commented Dec 30, 2015

Any non-trivial development using the Entity Framework will encounter this limitation.

It also has consequences on other technologies likes the OData protocol, because there is really no point to adding filtered $expands to the protocol if EF does not support them.

For those who are not (yet) familiar with the internals of EF Core, could you point us to the parts of the Entity Framework that would be impacted in order support this ?

@joshmouch

This comment has been minimized.

Show comment
Hide comment
@joshmouch

joshmouch Jan 21, 2016

I too would love this feature.

I too would love this feature.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Jul 25, 2016

@rowanmiller so what is the current way of using left join with a where clause \ on clause?
I currently query for the entire relationship and filter on the client.
Is there a better way of doing it?

var story = await _context.Stories
    .Include(x => x.Paragraphs)
    .Include(x => x.User)
    .Include(x => x.Tips)
    .Include(x => x.Images)
    .Include(x => x.Comments)
    .ThenInclude(x => x.User)
    .SingleOrDefaultAsync(x => x.Id == storyId);
if (story == null)
    return null;

story.Comments = story.Comments.Where(x => !x.IsDeleted).ToList();
story.Images = story.Images.Where(x => !x.IsDeleted).ToList();
story.Paragraphs = story.Paragraphs.Where(x => !x.IsDeleted).ToList();
story.Tips = story.Tips.Where(x => !x.IsDeleted).ToList();
return story;

It's a mess... and bad performance-wise.

gdoron commented Jul 25, 2016

@rowanmiller so what is the current way of using left join with a where clause \ on clause?
I currently query for the entire relationship and filter on the client.
Is there a better way of doing it?

var story = await _context.Stories
    .Include(x => x.Paragraphs)
    .Include(x => x.User)
    .Include(x => x.Tips)
    .Include(x => x.Images)
    .Include(x => x.Comments)
    .ThenInclude(x => x.User)
    .SingleOrDefaultAsync(x => x.Id == storyId);
if (story == null)
    return null;

story.Comments = story.Comments.Where(x => !x.IsDeleted).ToList();
story.Images = story.Images.Where(x => !x.IsDeleted).ToList();
story.Paragraphs = story.Paragraphs.Where(x => !x.IsDeleted).ToList();
story.Tips = story.Tips.Where(x => !x.IsDeleted).ToList();
return story;

It's a mess... and bad performance-wise.

@lucacestola

This comment has been minimized.

Show comment
Hide comment
@lucacestola

lucacestola Jul 25, 2016

Will Filtered Loading be supported at configuration level, in order to have one to many navigation property filtered upstream? Can this feature be someway useful to avoid bad configurations with circular reference like this?

Will Filtered Loading be supported at configuration level, in order to have one to many navigation property filtered upstream? Can this feature be someway useful to avoid bad configurations with circular reference like this?

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Jul 25, 2016

@lucacestola I'm not sure why you think it's related to conditional querying of a navigation property.

gdoron commented Jul 25, 2016

@lucacestola I'm not sure why you think it's related to conditional querying of a navigation property.

@lucacestola

This comment has been minimized.

Show comment
Hide comment
@lucacestola

lucacestola Jul 25, 2016

@gdoron because it could be also applyed to one to many relationships and would be implicit.

Actually, with EF 6, I was not yet able to find a good solution for the relation type like the one at the posted link, without using a circular FK and, at the meantime, have the possibility to use an expression like this: parent.MainChild.ChildProperty.

I know that this kind of relations depends on a very custom logic so there is no simple way to address such a need, and I was hoping that, configuring the way relationships are loaded could almost partially address the issue.

@gdoron because it could be also applyed to one to many relationships and would be implicit.

Actually, with EF 6, I was not yet able to find a good solution for the relation type like the one at the posted link, without using a circular FK and, at the meantime, have the possibility to use an expression like this: parent.MainChild.ChildProperty.

I know that this kind of relations depends on a very custom logic so there is no simple way to address such a need, and I was hoping that, configuring the way relationships are loaded could almost partially address the issue.

@Bartmax

This comment has been minimized.

Show comment
Hide comment
@Bartmax

Bartmax Jul 25, 2016

I just have the exactly same need as @gdoron (and not surprising, with IsDeleted fields as well)
is there any way to left join w/ where at db level?

Bartmax commented Jul 25, 2016

I just have the exactly same need as @gdoron (and not surprising, with IsDeleted fields as well)
is there any way to left join w/ where at db level?

@armartinez

This comment has been minimized.

Show comment
Hide comment
@armartinez

armartinez Sep 5, 2016

I'm also in the @gdoron scenario, but I return a collection instead of a single record so I'm doing a foreach on the collection and something like
story.Comments = story.Comments.Where(x => !x.IsDeleted).ToList();
on each record.
I've tried this http://stackoverflow.com/questions/4720573/linq-to-entities-how-to-filter-on-child-entities/4724297#4724297 but it doesn't seem to work on EF Core. Is there a better way to do this?

I'm also in the @gdoron scenario, but I return a collection instead of a single record so I'm doing a foreach on the collection and something like
story.Comments = story.Comments.Where(x => !x.IsDeleted).ToList();
on each record.
I've tried this http://stackoverflow.com/questions/4720573/linq-to-entities-how-to-filter-on-child-entities/4724297#4724297 but it doesn't seem to work on EF Core. Is there a better way to do this?

@arielcloud

This comment has been minimized.

Show comment
Hide comment
@arielcloud

arielcloud Sep 5, 2016

You can query stories without including comments, then query separately comments and Explicit loading them: https://docs.efproject.net/en/latest/querying/related-data.html

You can query stories without including comments, then query separately comments and Explicit loading them: https://docs.efproject.net/en/latest/querying/related-data.html

@armartinez

This comment has been minimized.

Show comment
Hide comment
@armartinez

armartinez Sep 5, 2016

Looks interesting, but I need to filter the first query to only return a record if there are any results in the specific navigation property, so I need to have the include or change the result of the first query when the explicit loading doesn't return anything which I think it's worse.

Looks interesting, but I need to filter the first query to only return a record if there are any results in the specific navigation property, so I need to have the include or change the result of the first query when the explicit loading doesn't return anything which I think it's worse.

@atrauzzi

This comment has been minimized.

Show comment
Hide comment
@atrauzzi

atrauzzi Oct 6, 2016

Yikes, don't know why this is sitting idle in a backlog. Should be considered for any upcoming version as per what the comments from @mikes-gh and @rendmath imply. Easy to overlook this one.

atrauzzi commented Oct 6, 2016

Yikes, don't know why this is sitting idle in a backlog. Should be considered for any upcoming version as per what the comments from @mikes-gh and @rendmath imply. Easy to overlook this one.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Oct 6, 2016

@atrauzzi well, this feature was and still is idle for years in EF, so I'm afraid ... 😢
Not sure why it's not prioritized.

gdoron commented Oct 6, 2016

@atrauzzi well, this feature was and still is idle for years in EF, so I'm afraid ... 😢
Not sure why it's not prioritized.

@HappyNomad

This comment has been minimized.

Show comment
Hide comment
@HappyNomad

HappyNomad Nov 1, 2016

Yes, this feature request has been around a while. I found it posted on UserVoice since 2010. It's crucial for allowing me to properly load my complex data model, so I hope it's soon given higher priority.

Yes, this feature request has been around a while. I found it posted on UserVoice since 2010. It's crucial for allowing me to properly load my complex data model, so I hope it's soon given higher priority.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 21, 2016

@rowanmiller @divega Can you please share with us when if ever this is going to be implemented?
We designed our data structure in a way that is best practice regarding DB design, but heavily rely on this feature.

Consider this simplified scheme:

public class Post
{
    public int Id { get; set; }
    public string Text { get; set; }
    public List<PostImage> Images { get; set; }
}

public class PostImage
{
    public int Id { get; set; }
    public bool IsDeleted { get; set; }
    public Post Post { get; set; }
    public int PostId { get; set; }
    public string Url { get; set; }
    public string CdnUrl { get; set; }
    public ImageType Type { get; set; }
}

public enum ImageType
{
    Normal = 0,
    Primary = 1,
    Header = 2,
    Profile = 3
}

Now lets say I want to query 10 posts for my blog homepage with their single Primary image.
Currently, there is no way of doing it.
I will have to query for 10 posts with ALL of their images (even the deleted ones!) and only on the client filter out the useless data.

As our application is getting more sophisticated and gets more traffic, this is becoming a real and significant pain and we need a solution for this.

Is it going to have the same luck as the feature request on EF which was and still is idle for 6 years?

We really need an answer, there are solutions like denormalize our data model but that's rarely a good idea.

Thanks!

gdoron commented Nov 21, 2016

@rowanmiller @divega Can you please share with us when if ever this is going to be implemented?
We designed our data structure in a way that is best practice regarding DB design, but heavily rely on this feature.

Consider this simplified scheme:

public class Post
{
    public int Id { get; set; }
    public string Text { get; set; }
    public List<PostImage> Images { get; set; }
}

public class PostImage
{
    public int Id { get; set; }
    public bool IsDeleted { get; set; }
    public Post Post { get; set; }
    public int PostId { get; set; }
    public string Url { get; set; }
    public string CdnUrl { get; set; }
    public ImageType Type { get; set; }
}

public enum ImageType
{
    Normal = 0,
    Primary = 1,
    Header = 2,
    Profile = 3
}

Now lets say I want to query 10 posts for my blog homepage with their single Primary image.
Currently, there is no way of doing it.
I will have to query for 10 posts with ALL of their images (even the deleted ones!) and only on the client filter out the useless data.

As our application is getting more sophisticated and gets more traffic, this is becoming a real and significant pain and we need a solution for this.

Is it going to have the same luck as the feature request on EF which was and still is idle for 6 years?

We really need an answer, there are solutions like denormalize our data model but that's rarely a good idea.

Thanks!

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Nov 21, 2016

Member

@gdoron we do want to do this, but it's not at the top of the list. Our Roadmap will give you an idea of the things that are going to be worked on next. You will see that this is listed under "High Priority", but just not the "Critical O/RM" list.

Member

rowanmiller commented Nov 21, 2016

@gdoron we do want to do this, but it's not at the top of the list. Our Roadmap will give you an idea of the things that are going to be worked on next. You will see that this is listed under "High Priority", but just not the "Critical O/RM" list.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

@rowanmiller I'm sure everyone has different points of view and needs but here are my two cents:
Most of the things that are missing have somewhat reasonable workarounds.

e.g.
Lazy load - simply Include upfront all your data.
View mapping- Manually create a migration.
SP Mapping - Use some technique as with View.
etc.

But Filtered Include has 0 reasonable workarounds.
The only workaround is writing raw SQL but in many cases you need it for almost all of your queries, so that's not an option or else why use an ORM to begin with.

So reiterating what @mikes-gh wrote months ago:

Don't underestimate the value of filtered include. It was a top request in ef 6.
I came across this requirement on my first ef 7 project.
I'd take that over lazy loading any day.

I had already 3 projects on EF Core, and it was a requirement and a pain in ALL of them.

gdoron commented Nov 22, 2016

@rowanmiller I'm sure everyone has different points of view and needs but here are my two cents:
Most of the things that are missing have somewhat reasonable workarounds.

e.g.
Lazy load - simply Include upfront all your data.
View mapping- Manually create a migration.
SP Mapping - Use some technique as with View.
etc.

But Filtered Include has 0 reasonable workarounds.
The only workaround is writing raw SQL but in many cases you need it for almost all of your queries, so that's not an option or else why use an ORM to begin with.

So reiterating what @mikes-gh wrote months ago:

Don't underestimate the value of filtered include. It was a top request in ef 6.
I came across this requirement on my first ef 7 project.
I'd take that over lazy loading any day.

I had already 3 projects on EF Core, and it was a requirement and a pain in ALL of them.

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Nov 22, 2016

Member

Just to be clear, the items on the roadmap are the very top of the 100s of feature requests we have sitting on the backlog. So it's inclusion on the list means that it is one of our top priorities. The split between "Critical" and "High Priority" is always subjective. The current split is based on our imperfect aggregation of the feedback from all our customers.

It's not as clean as true filtered loading support, but you can do something like this to do filtered loading. It will run two queries, but that is what EF Core would do under the covers anyway, when you load a collection.

var blogs = db.Blogs
    .Where(b => b.Rating> 3)
    .ToList();

var blogIds = blogs.Select(b => b.BlogId).ToList();

db.Posts.Where(p => blogsIds.Contains(p.BlogId))
    .Where(p => p.Rating > 3)
    .Load();
Member

rowanmiller commented Nov 22, 2016

Just to be clear, the items on the roadmap are the very top of the 100s of feature requests we have sitting on the backlog. So it's inclusion on the list means that it is one of our top priorities. The split between "Critical" and "High Priority" is always subjective. The current split is based on our imperfect aggregation of the feedback from all our customers.

It's not as clean as true filtered loading support, but you can do something like this to do filtered loading. It will run two queries, but that is what EF Core would do under the covers anyway, when you load a collection.

var blogs = db.Blogs
    .Where(b => b.Rating> 3)
    .ToList();

var blogIds = blogs.Select(b => b.BlogId).ToList();

db.Posts.Where(p => blogsIds.Contains(p.BlogId))
    .Where(p => p.Rating > 3)
    .Load();
@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

@rowanmiller

It will run two queries, but that is what EF Core would do under the covers anyway, when you load a collection.

I thought it's a temporary limitation that you're working on fixing.
Are you telling me it is by design?
Because it's not just two queries, it's two round trips to the DB.

Anyway, it might be acceptable for one collection loading, but when you have 10 included entities (we already have 6-7 in some places,), that means 11 round trips or querying the DB with 10 connections concurrently.

I might got you wrong, but if I didn't... Houston we have a problem.

gdoron commented Nov 22, 2016

@rowanmiller

It will run two queries, but that is what EF Core would do under the covers anyway, when you load a collection.

I thought it's a temporary limitation that you're working on fixing.
Are you telling me it is by design?
Because it's not just two queries, it's two round trips to the DB.

Anyway, it might be acceptable for one collection loading, but when you have 10 included entities (we already have 6-7 in some places,), that means 11 round trips or querying the DB with 10 connections concurrently.

I might got you wrong, but if I didn't... Houston we have a problem.

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Nov 22, 2016

Member

cc @anpete and @divega who can provide some more context. But in general, the EF Core approach out performs the EF6.x approach pretty consistently.

Member

rowanmiller commented Nov 22, 2016

cc @anpete and @divega who can provide some more context. But in general, the EF Core approach out performs the EF6.x approach pretty consistently.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

I find it very hard to believe EF Core is or will be faster because of this approach.
You might have fixed some internal slow parts that caused slow execution?

I believe several roundtrips will never be as fast as a single well written query.
That just doesn't make any sense to me.
I can ask my ex-CTO which is a SQL-Server MVP for his input if you like @rowanmiller.

gdoron commented Nov 22, 2016

I find it very hard to believe EF Core is or will be faster because of this approach.
You might have fixed some internal slow parts that caused slow execution?

I believe several roundtrips will never be as fast as a single well written query.
That just doesn't make any sense to me.
I can ask my ex-CTO which is a SQL-Server MVP for his input if you like @rowanmiller.

@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Nov 22, 2016

@gdoron We never execute n+1 queries for Include. For your collection example, we would execute two queries, one for the parents and one for all of the children of those parents.

EF6 would execute one single left outer join query, which results in the dreaded cartesian product result set - The parent data is duplicated for each child row in the results.

anpete commented Nov 22, 2016

@gdoron We never execute n+1 queries for Include. For your collection example, we would execute two queries, one for the parents and one for all of the children of those parents.

EF6 would execute one single left outer join query, which results in the dreaded cartesian product result set - The parent data is duplicated for each child row in the results.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

@anpete that's a relief... 👍 😄
Thanks for clarifying!

gdoron commented Nov 22, 2016

@anpete that's a relief... 👍 😄
Thanks for clarifying!

@rowanmiller

This comment has been minimized.

Show comment
Hide comment
@rowanmiller

rowanmiller Nov 22, 2016

Member

This is probably obvious, but that's also what the workaround code I listed does. It's two queries, not n+1.

Member

rowanmiller commented Nov 22, 2016

This is probably obvious, but that's also what the workaround code I listed does. It's two queries, not n+1.

@Bartmax

This comment has been minimized.

Show comment
Hide comment
@Bartmax

Bartmax Nov 22, 2016

In the example you provided,

var blogs = db.Blogs
    .Where(b => b.Rating> 3)
    .ToList();

var blogIds = blogs.Select(b => b.BlogId).ToList();

db.Posts.Where(p => blogsIds.Contains(p.BlogId))
    .Where(p => p.Rating > 3)
    .Load();

how should I also include Blog.Images ? Do I need a 3rd query?

db.Images.Where(i => blogsIds.Contains(i.BlogId))
    .Where(i => !i.IsDeleted)
    .Load();

For your collection example, we would execute two queries, one for the parents and one for all of the children of those parents.

I don't see 1 query for parents and 1 for ALL childrens, instead I see one query PER children.

Am i missing something?

Not to mention about other type of filtering like Take or Skip ... that makes the whole deal a lot uglier and complicated with GroupBy afaik. #7033

I really think the most on point comment is:

Don't underestimate the value of filtered include.

Bartmax commented Nov 22, 2016

In the example you provided,

var blogs = db.Blogs
    .Where(b => b.Rating> 3)
    .ToList();

var blogIds = blogs.Select(b => b.BlogId).ToList();

db.Posts.Where(p => blogsIds.Contains(p.BlogId))
    .Where(p => p.Rating > 3)
    .Load();

how should I also include Blog.Images ? Do I need a 3rd query?

db.Images.Where(i => blogsIds.Contains(i.BlogId))
    .Where(i => !i.IsDeleted)
    .Load();

For your collection example, we would execute two queries, one for the parents and one for all of the children of those parents.

I don't see 1 query for parents and 1 for ALL childrens, instead I see one query PER children.

Am i missing something?

Not to mention about other type of filtering like Take or Skip ... that makes the whole deal a lot uglier and complicated with GroupBy afaik. #7033

I really think the most on point comment is:

Don't underestimate the value of filtered include.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

@rowanmiller @anpete actually I'm not sure we understood each other correctly.
I wasn't talking about N+1 where N = number of rows, but where N=number of included properties.

So in case I have a query like:

context.Post
.Include(x=> x.Images)
.Include(x=> x.Paragraphs)
.Include(x=> x.As)
.Include(x=> x.Bs)
.Include(x=> x.Cs)
.Include(x=> x.Ds)
.Where(x => x.Id == 1)
.ToList()

We'll have 1 query for the post, and another 6 queries for the navigation properties, am I right?
If I am, that's bad even if it's not 6 round trips.

gdoron commented Nov 22, 2016

@rowanmiller @anpete actually I'm not sure we understood each other correctly.
I wasn't talking about N+1 where N = number of rows, but where N=number of included properties.

So in case I have a query like:

context.Post
.Include(x=> x.Images)
.Include(x=> x.Paragraphs)
.Include(x=> x.As)
.Include(x=> x.Bs)
.Include(x=> x.Cs)
.Include(x=> x.Ds)
.Where(x => x.Id == 1)
.ToList()

We'll have 1 query for the post, and another 6 queries for the navigation properties, am I right?
If I am, that's bad even if it's not 6 round trips.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

@anpete @rowanmiller
Just had a phone call with a SQL-Server MVP, a summary of what he said:

  1. To SQL Server it doesn't matter if you'll have a single query or 10, the redundant fields returned have 0 impact on SQL Server.
  2. Splitting the queries is what SQL is doing internally anyway, and when people try to optimize SQL, it's usually to the worst as SQL is doing better when not forcing it do act in a specific way.
  3. Having multiple queries have overhead on SQL.
  4. The only thing that actually splitting queries solves is bandwidth on the network as there will be less bytes transferred over the wire, and he says it's negligible compared to having multiple queries.

EOF.

gdoron commented Nov 22, 2016

@anpete @rowanmiller
Just had a phone call with a SQL-Server MVP, a summary of what he said:

  1. To SQL Server it doesn't matter if you'll have a single query or 10, the redundant fields returned have 0 impact on SQL Server.
  2. Splitting the queries is what SQL is doing internally anyway, and when people try to optimize SQL, it's usually to the worst as SQL is doing better when not forcing it do act in a specific way.
  3. Having multiple queries have overhead on SQL.
  4. The only thing that actually splitting queries solves is bandwidth on the network as there will be less bytes transferred over the wire, and he says it's negligible compared to having multiple queries.

EOF.

@Bartmax

This comment has been minimized.

Show comment
Hide comment
@Bartmax

Bartmax Nov 22, 2016

@gdoron i don't think it's that black or white, and pretty sure @rowanmiller (and the ef team) understands very much the internals of SQL and ORMs. I wouldn't even dare to question that.

I think the item being in high priority should be enough, they know it's important and they will add it. But for some it's critical and for others is high priority. This thread focused on make it a more priority item, not disusing the design whatsoever.

On my scenarios, even I would love to have filtered includes and I would use it on every project. It's not critically blocking me. High priority sounds reasonable, but I don't mind if it make to critical either.
And actually, I'm more interested on the api consumption than on query performance.

Bartmax commented Nov 22, 2016

@gdoron i don't think it's that black or white, and pretty sure @rowanmiller (and the ef team) understands very much the internals of SQL and ORMs. I wouldn't even dare to question that.

I think the item being in high priority should be enough, they know it's important and they will add it. But for some it's critical and for others is high priority. This thread focused on make it a more priority item, not disusing the design whatsoever.

On my scenarios, even I would love to have filtered includes and I would use it on every project. It's not critically blocking me. High priority sounds reasonable, but I don't mind if it make to critical either.
And actually, I'm more interested on the api consumption than on query performance.

@gdoron

This comment has been minimized.

Show comment
Hide comment
@gdoron

gdoron Nov 22, 2016

pretty sure @rowanmiller (and the ef team) understands very much the internals of SQL and ORMs. I wouldn't even dare to question that.

I never did... and I apologize to the team if I was understood otherwise!
It never hurts to hear another expert though.

gdoron commented Nov 22, 2016

pretty sure @rowanmiller (and the ef team) understands very much the internals of SQL and ORMs. I wouldn't even dare to question that.

I never did... and I apologize to the team if I was understood otherwise!
It never hurts to hear another expert though.

@dodegaard

This comment has been minimized.

Show comment
Hide comment
@dodegaard

dodegaard Nov 4, 2017

I have now encountered a .Include() that crashes a C# console app when the amount of data that an include brings with it exceeds a certain threshold. I don't know the exact level of data but this illustrates why a filtered include would be beneficial. The main issue for me was the Unhandled exception when iterating the in-memory list of the objects was never the same. I suppose one could argue that this could be an overall .ToList() memory issue but without the ability to filter on the Include I was forced to alter data in a down system situation last night to overcome the limitation. This would be a huge win for those of us who find Include very helpful yet prone to data overload.

I have now encountered a .Include() that crashes a C# console app when the amount of data that an include brings with it exceeds a certain threshold. I don't know the exact level of data but this illustrates why a filtered include would be beneficial. The main issue for me was the Unhandled exception when iterating the in-memory list of the objects was never the same. I suppose one could argue that this could be an overall .ToList() memory issue but without the ability to filter on the Include I was forced to alter data in a down system situation last night to overcome the limitation. This would be a huge win for those of us who find Include very helpful yet prone to data overload.

@divega

This comment has been minimized.

Show comment
Hide comment
@divega

divega Nov 4, 2017

Member

@dodegaard In case it helps, have you had a chance to look at the new query filters feature supported by EF Core 2.0? Would that help in your scenario?

Member

divega commented Nov 4, 2017

@dodegaard In case it helps, have you had a chance to look at the new query filters feature supported by EF Core 2.0? Would that help in your scenario?

@divega

This comment has been minimized.

Show comment
Hide comment
@divega

divega Nov 4, 2017

Member

@ajbeaven As you very well understand, the team considers that the priority of this feature is less because the overlap with query filters. It is very hard to asses what the current priority should be. One way you may be able to help is by articulating the scenarios in which you think this feature is still necessary but query filters can’t help.

Member

divega commented Nov 4, 2017

@ajbeaven As you very well understand, the team considers that the priority of this feature is less because the overlap with query filters. It is very hard to asses what the current priority should be. One way you may be able to help is by articulating the scenarios in which you think this feature is still necessary but query filters can’t help.

@ajbeaven

This comment has been minimized.

Show comment
Hide comment
@ajbeaven

ajbeaven Nov 5, 2017

@divega There has been a handful of times where I've needed to load a subset of data for one query, but not for another. Here are a couple of examples:

var parts = _context.Parts
    .Include(c => c.Performances.Where(p => p.PerformerId == _currentUser.UserId));
var plays = _context.Plays
    .Include(c => c.Parts.Where(p => p.CanAudition));

Neither of these includes make sense on global level filter.

I'm also using AutoMapper's .ProjectTo to easily map EF datasets directly to ViewModels without loading superfluous data. Without filtered includes allowing me to load the exact dataset, I need to do some additional filtering after the mapper had done its work, which somewhat defeats the purpose.

ajbeaven commented Nov 5, 2017

@divega There has been a handful of times where I've needed to load a subset of data for one query, but not for another. Here are a couple of examples:

var parts = _context.Parts
    .Include(c => c.Performances.Where(p => p.PerformerId == _currentUser.UserId));
var plays = _context.Plays
    .Include(c => c.Parts.Where(p => p.CanAudition));

Neither of these includes make sense on global level filter.

I'm also using AutoMapper's .ProjectTo to easily map EF datasets directly to ViewModels without loading superfluous data. Without filtered includes allowing me to load the exact dataset, I need to do some additional filtering after the mapper had done its work, which somewhat defeats the purpose.

@popcatalin81

This comment has been minimized.

Show comment
Hide comment
@popcatalin81

popcatalin81 Nov 6, 2017

@ajbeaven Projections aren't done using 'Include' and includes are not used during projections.
(https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions)

popcatalin81 commented Nov 6, 2017

@ajbeaven Projections aren't done using 'Include' and includes are not used during projections.
(https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions)

@ajbeaven

This comment has been minimized.

Show comment
Hide comment
@ajbeaven

ajbeaven Nov 6, 2017

@popcatalin81 Yikes, thanks for putting me straight there! I was confused between one mapping that used ProjectTo and another that used the Mapper.Map (the latter did require Includes to be specified).

That aside, the examples above are still valid use-cases as far as I'm concerned.

ajbeaven commented Nov 6, 2017

@popcatalin81 Yikes, thanks for putting me straight there! I was confused between one mapping that used ProjectTo and another that used the Mapper.Map (the latter did require Includes to be specified).

That aside, the examples above are still valid use-cases as far as I'm concerned.

@xr280xr

This comment has been minimized.

Show comment
Hide comment
@xr280xr

xr280xr Nov 27, 2017

I absolutely need this and can't imagine any serious medium to large-scale, data-centered application not needing it. I'm shocked it has sat in the backlogs for coming up on a decade.

xr280xr commented Nov 27, 2017

I absolutely need this and can't imagine any serious medium to large-scale, data-centered application not needing it. I'm shocked it has sat in the backlogs for coming up on a decade.

@niccha

This comment has been minimized.

Show comment
Hide comment
@niccha

niccha Dec 8, 2017

I also need this feature and encountered it on my first project with EF. Like others say, can't see many projects that won't need this feature...

niccha commented Dec 8, 2017

I also need this feature and encountered it on my first project with EF. Like others say, can't see many projects that won't need this feature...

@jhvanderven

This comment has been minimized.

Show comment
Hide comment
@jhvanderven

jhvanderven Dec 13, 2017

The workaround looks ugly. .Include(..).Where(..) is a readable, understandable syntax. Please Include this feature fast.

The workaround looks ugly. .Include(..).Where(..) is a readable, understandable syntax. Please Include this feature fast.

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Jan 31, 2018

1+, this is a must-have feature (I think... this is a very basic feature. All of my projects need this).

Example:
var users = _context.Users.Include(u => u.Permissions.Where(p => p.PermissionType == 1));

mhosman commented Jan 31, 2018

1+, this is a must-have feature (I think... this is a very basic feature. All of my projects need this).

Example:
var users = _context.Users.Include(u => u.Permissions.Where(p => p.PermissionType == 1));

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 1, 2018

Hey @rowanmiller @ajcvickers this is something that can be done? You have any estimated time for this? Thanks!!!

mhosman commented Feb 1, 2018

Hey @rowanmiller @ajcvickers this is something that can be done? You have any estimated time for this? Thanks!!!

@ajcvickers

This comment has been minimized.

Show comment
Hide comment
@ajcvickers

ajcvickers Feb 1, 2018

Member

@mhosman This issue is in the Backlog milestone. This means that it is not going to happen for the 2.1 release. We will re-assess the backlog following the 2.1 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

Member

ajcvickers commented Feb 1, 2018

@mhosman This issue is in the Backlog milestone. This means that it is not going to happen for the 2.1 release. We will re-assess the backlog following the 2.1 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

Hey @ajcvickers thank you very much for your response. The only approach here is to make a raw SQL query? Maybe there is some example to mix a full lambda query with include and add a FromSQL to filter the Include? Or maybe make an include and then filter the results manually? (this last option is not performant).

mhosman commented Feb 2, 2018

Hey @ajcvickers thank you very much for your response. The only approach here is to make a raw SQL query? Maybe there is some example to mix a full lambda query with include and add a FromSQL to filter the Include? Or maybe make an include and then filter the results manually? (this last option is not performant).

@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Feb 2, 2018

@mhosman Global query filters (HasQueryFilter API in OnModelCreating) are one way to do this.

anpete commented Feb 2, 2018

@mhosman Global query filters (HasQueryFilter API in OnModelCreating) are one way to do this.

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

Hey @anpete I know that, but I need to make a filter based on a specific value that changes all the time.

mhosman commented Feb 2, 2018

Hey @anpete I know that, but I need to make a filter based on a specific value that changes all the time.

@TsengSR

This comment has been minimized.

Show comment
Hide comment
@TsengSR

TsengSR Feb 2, 2018

@mhosman IIRC you can use member properties of the DbContext to do that already with the filtering API we have now. You just need to set the value, before executing the query. There are no concurrency issues as EF isn't thread-safe, so you can only do one query at a time

TsengSR commented Feb 2, 2018

@mhosman IIRC you can use member properties of the DbContext to do that already with the filtering API we have now. You just need to set the value, before executing the query. There are no concurrency issues as EF isn't thread-safe, so you can only do one query at a time

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

@anpete @TsengSR Could you please provide some basic workaround example based on this example that I'm trying to apply (using lambda)??

var users = _context.Users.Include(u => u.Permissions.Where(p => p.PermissionType == 1));

Thank you very much!

mhosman commented Feb 2, 2018

@anpete @TsengSR Could you please provide some basic workaround example based on this example that I'm trying to apply (using lambda)??

var users = _context.Users.Include(u => u.Permissions.Where(p => p.PermissionType == 1));

Thank you very much!

@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Feb 2, 2018

@mhosman

Add a _permissionType field to your context and initialize the value from a ctor argument.
Setup a filter on the Permission ET like:
modelBuilder.Entity<Permission>().HasQueryFilter(p => p.PermissionType == _permissionType);
Now any query for Permission will be filtered by the current value of _permissionType.

anpete commented Feb 2, 2018

@mhosman

Add a _permissionType field to your context and initialize the value from a ctor argument.
Setup a filter on the Permission ET like:
modelBuilder.Entity<Permission>().HasQueryFilter(p => p.PermissionType == _permissionType);
Now any query for Permission will be filtered by the current value of _permissionType.

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

@anpete Do you mean to initialize the value in the PermissionType Class? (sorry my confusion but I can't see where to initialize that specific value for that specific query in the controller).

mhosman commented Feb 2, 2018

@anpete Do you mean to initialize the value in the PermissionType Class? (sorry my confusion but I can't see where to initialize that specific value for that specific query in the controller).

@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Feb 2, 2018

The normal way is to have the value initialized when creating the context:

var context = new MyContext(permissionType: 1);

In this case, the value is "set" for the lifetime of that specific context instance. Other instances can have difference values.

You should also be able to add a PermissionType property to your context.

var context = new MyContext();
context.PermissionType = 1;
var q = context.Users.Include(u => u.Permissions).ToList();

This is less common but should allow you to change the value on the fly.

anpete commented Feb 2, 2018

The normal way is to have the value initialized when creating the context:

var context = new MyContext(permissionType: 1);

In this case, the value is "set" for the lifetime of that specific context instance. Other instances can have difference values.

You should also be able to add a PermissionType property to your context.

var context = new MyContext();
context.PermissionType = 1;
var q = context.Users.Include(u => u.Permissions).ToList();

This is less common but should allow you to change the value on the fly.

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

Great @anpete! Thank you very much for your help!

mhosman commented Feb 2, 2018

Great @anpete! Thank you very much for your help!

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

@anpete Just one last question. How to access _permissionType attribute from a Self-contained type configuration file?

mhosman commented Feb 2, 2018

@anpete Just one last question. How to access _permissionType attribute from a Self-contained type configuration file?

@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Feb 2, 2018

@smitpatel Passing in the context to the entity configuration works, right?

anpete commented Feb 2, 2018

@smitpatel Passing in the context to the entity configuration works, right?

@smitpatel

This comment has been minimized.

Show comment
Hide comment
@smitpatel

smitpatel Feb 2, 2018

Contributor

No. See issue #10301

Contributor

smitpatel commented Feb 2, 2018

No. See issue #10301

@mhosman

This comment has been minimized.

Show comment
Hide comment
@mhosman

mhosman Feb 2, 2018

Yes, passing the context to a file with this example code:

class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
  public void Configure(EntityTypeBuilder<Customer> builder)
  {
     builder.HasKey(c => c.AlternateKey);
     builder.Property(c => c.Name).HasMaxLength(200);
   }
}

mhosman commented Feb 2, 2018

Yes, passing the context to a file with this example code:

class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
  public void Configure(EntityTypeBuilder<Customer> builder)
  {
     builder.HasKey(c => c.AlternateKey);
     builder.Property(c => c.Name).HasMaxLength(200);
   }
}
@anpete

This comment has been minimized.

Show comment
Hide comment
@anpete

anpete Feb 2, 2018

Thanks @smitpatel

@mhosman For now you will need to define the filters in OnModelCreating directly

anpete commented Feb 2, 2018

Thanks @smitpatel

@mhosman For now you will need to define the filters in OnModelCreating directly

@weitzhandler

This comment has been minimized.

Show comment
Hide comment
@weitzhandler

weitzhandler Mar 7, 2018

Contributor

How about:

.Include(f => f.Thumbnails
  .Where(t => t.ThumbnailSize < maxThumbSize)
  .OrderBy(t => t.Rank)
  .Take(3))
.ThenInclude(...)
Contributor

weitzhandler commented Mar 7, 2018

How about:

.Include(f => f.Thumbnails
  .Where(t => t.ThumbnailSize < maxThumbSize)
  .OrderBy(t => t.Rank)
  .Take(3))
.ThenInclude(...)
@stap123

This comment has been minimized.

Show comment
Hide comment
@stap123

stap123 Mar 13, 2018

Just want to throw a +1 onto this, would be excellent to have this feature I commonly hit this limitation.

stap123 commented Mar 13, 2018

Just want to throw a +1 onto this, would be excellent to have this feature I commonly hit this limitation.

@n123r

This comment has been minimized.

Show comment
Hide comment
@n123r

n123r Apr 21, 2018

Also adding a +1 onto this feature. The ability to filter on include on a per query basis would be an excellent addition to EF Core

n123r commented Apr 21, 2018

Also adding a +1 onto this feature. The ability to filter on include on a per query basis would be an excellent addition to EF Core

@conterio

This comment has been minimized.

Show comment
Hide comment
@conterio

conterio Apr 24, 2018

It's been a couple years now! Work on this feature please!!!!! Query on Includes. I'm going to Ignite this year, have it done by then or else. Or else what? Or else i'll just have to keep waiting.

It's been a couple years now! Work on this feature please!!!!! Query on Includes. I'm going to Ignite this year, have it done by then or else. Or else what? Or else i'll just have to keep waiting.

@orobert91

This comment has been minimized.

Show comment
Hide comment
@orobert91

orobert91 May 25, 2018

I also upvote this feature, and yes I know about global query filters and it doesn't solve any of my use cases.

I also upvote this feature, and yes I know about global query filters and it doesn't solve any of my use cases.

@SonicGD

This comment has been minimized.

Show comment
Hide comment
@SonicGD

SonicGD Jun 14, 2018

+1 to this feature. Global filters doesn't solve my problems, i need to set condition on per-query basis

SonicGD commented Jun 14, 2018

+1 to this feature. Global filters doesn't solve my problems, i need to set condition on per-query basis

@ajbeaven

This comment has been minimized.

Show comment
Hide comment
@ajbeaven

ajbeaven Jun 20, 2018

Can we lock new comments on this issue? I'm keen to hear progress on this but don't want to be spammed by inane +1 comments.

If you wish to throw support behind this issue, thumbs up the OP and subscribe to notifications. The fourth comment here says that this will happen at some point, so either be patient or create a pull request.

Can we lock new comments on this issue? I'm keen to hear progress on this but don't want to be spammed by inane +1 comments.

If you wish to throw support behind this issue, thumbs up the OP and subscribe to notifications. The fourth comment here says that this will happen at some point, so either be patient or create a pull request.

@HairyPorker

This comment has been minimized.

Show comment
Hide comment
@HairyPorker

HairyPorker Jun 22, 2018

to OP, my current workaround is to use LINQ join

to OP, my current workaround is to use LINQ join

@jmatter

This comment has been minimized.

Show comment
Hide comment
@jmatter

jmatter Jun 27, 2018

I use the following workaround:

var entity = context.Table.First();
context.Entry(entity)
                        .Collection(parent => parent.myChildTable)
                        .Query()
                        .Where(child => child.amount > 100)
                        .ToList();

The collection of myChildTable inside the parent entity then gets populated with the filtered entities.

jmatter commented Jun 27, 2018

I use the following workaround:

var entity = context.Table.First();
context.Entry(entity)
                        .Collection(parent => parent.myChildTable)
                        .Query()
                        .Where(child => child.amount > 100)
                        .ToList();

The collection of myChildTable inside the parent entity then gets populated with the filtered entities.

@KuzDeveloper

This comment has been minimized.

Show comment
Hide comment
@KuzDeveloper

KuzDeveloper Jul 12, 2018

@jmatter How do you use this approach, when you want to retrieve list of items instead of just the first one, and also, when the child table also has children? So, like:

class A { List ListOfB; bool IsDeleted; int JustANumber; }
class B { List ListOfC; bool IsDeleted; int SomethingElse; }
class C { ... }

What I would normally do is this:

public IEnumerable GetFilteredListOfA(int parameter)
{
IEnumerable result = MyDbContext.ClassA.Where(a => !a.IsDeleted && JustANumber >= parameter).Include(a => a.ListOfB.Where(b => !b.IsDeleted && SomethingElse >= parameter).Include(b => b.ListOFC....);

Right now I need to use the .Select and create new typed instances, but the code is quite long and I had to break my domain driven approach as e.g. the Id field now cannot be set to private, else all my items will have the Id of 0 instead of the real one. So, with Select it looks like this:

IEnumerable result = MyDbContext.ClassA.Where(a => !a.IsDeleted && JustANumber >= parameter)
.Select(a => new ClassA()
{
Id = a.Id,
ListOfB = a.ListOfB.Where(...).Select(b => new ClassB() { Id = b.Id, ListOFC = ...
}

KuzDeveloper commented Jul 12, 2018

@jmatter How do you use this approach, when you want to retrieve list of items instead of just the first one, and also, when the child table also has children? So, like:

class A { List ListOfB; bool IsDeleted; int JustANumber; }
class B { List ListOfC; bool IsDeleted; int SomethingElse; }
class C { ... }

What I would normally do is this:

public IEnumerable GetFilteredListOfA(int parameter)
{
IEnumerable result = MyDbContext.ClassA.Where(a => !a.IsDeleted && JustANumber >= parameter).Include(a => a.ListOfB.Where(b => !b.IsDeleted && SomethingElse >= parameter).Include(b => b.ListOFC....);

Right now I need to use the .Select and create new typed instances, but the code is quite long and I had to break my domain driven approach as e.g. the Id field now cannot be set to private, else all my items will have the Id of 0 instead of the real one. So, with Select it looks like this:

IEnumerable result = MyDbContext.ClassA.Where(a => !a.IsDeleted && JustANumber >= parameter)
.Select(a => new ClassA()
{
Id = a.Id,
ListOfB = a.ListOfB.Where(...).Select(b => new ClassB() { Id = b.Id, ListOFC = ...
}

@YandyZaldivar

This comment has been minimized.

Show comment
Hide comment
@YandyZaldivar

YandyZaldivar Jul 25, 2018

Consider the scenario where instead of:
query.Include(p => p.Property)
we have:
query.Include("Xxx.Yyy.Zzz")
only the chained property names.

How are we going to add the Where, OrderBy, Take and Skip filters?

We can try to create some Expression for our property name:

static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{
	var parameter = Expression.Parameter(typeof(T));
	var property = Expression.Property(parameter, propertyName);
	var propAsObject = Expression.Convert(property, typeof(object));

	return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
}

or even something like for nested properties:
var body = propertyName.Split('.').Aggregate<string, Expression>(param, Expression.PropertyOrField);

But this seems an obscure path to me.

Consider the scenario where instead of:
query.Include(p => p.Property)
we have:
query.Include("Xxx.Yyy.Zzz")
only the chained property names.

How are we going to add the Where, OrderBy, Take and Skip filters?

We can try to create some Expression for our property name:

static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{
	var parameter = Expression.Parameter(typeof(T));
	var property = Expression.Property(parameter, propertyName);
	var propAsObject = Expression.Convert(property, typeof(object));

	return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
}

or even something like for nested properties:
var body = propertyName.Split('.').Aggregate<string, Expression>(param, Expression.PropertyOrField);

But this seems an obscure path to me.

@YandyZaldivar

This comment has been minimized.

Show comment
Hide comment
@YandyZaldivar

YandyZaldivar Jul 25, 2018

https://docs.microsoft.com/en-us/ef/core/querying/related-data

Tip
Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

What if we want to include only what we filter, and if we filter nothing for a specific query, include nothing?

Take into account that data obtained is potentially for being serialized over the network (to client apps), so it is not a good idea end up sending what we don't need.

https://docs.microsoft.com/en-us/ef/core/querying/related-data

Tip
Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

What if we want to include only what we filter, and if we filter nothing for a specific query, include nothing?

Take into account that data obtained is potentially for being serialized over the network (to client apps), so it is not a good idea end up sending what we don't need.

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