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

Query: reuse include pipeline for queries projecting uncomposed collection navigations #8584

Closed
maumar opened this issue May 25, 2017 · 2 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@maumar
Copy link
Contributor

maumar commented May 25, 2017

ctx.Customers.Select(c => c.Orders)

currently produces N+1 queries, however, similar query:

ctx.Customers.Include(c => c.Orders)

is much better, producing only 2 queries.

We should be able to leverage the include pipeline for the first query

@maumar maumar self-assigned this May 25, 2017
@maumar
Copy link
Contributor Author

maumar commented May 25, 2017

related to #8229

@ajcvickers ajcvickers added this to the 2.0.0 milestone May 26, 2017
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection)) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection) ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection) ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection) ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection) ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => SuppressNavigationRewrite(prm?.Reference?.Collection) ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied).
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 2, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
maumar added a commit that referenced this issue Jun 3, 2017
…ncomposed collection navigations

Currently when projecting collection navigation we produce N+1 queries. This change leverages include pipeline which produces 2 queries instead and joins the result on the client.

We only do this for collection navigation that are not composed on - otherwise, the query that happens after collection navigation would be performed on the client, so it's not clear that would be preferable to N+1.
Also as a side effect, we always materialize root entity (or all intermediate entities in case of multi-level navigation). This is a side effect of reusing Include pipeline, which always expects (and depends on) root element being materialized.

We leverage the include pipeline by performing a simple QM rewrite:

from [e] in entities
select new { [e].Id, [e].Reference.Collection }

will be translated to:

from [e] in entities
select new { [e].Id, _ProjectCollectionNavigation([e], prm => prm?.Reference?.Collection ?? new ICollection<Entity>()) }

additionally, we generate include result operator for [e].Reference.Collection.

When include pipeline processes the updated QM, it will apply the include on first argument to _ProjectCollectionNavigation.
Implementation of _ProjectCollectionNavigation simply invokes the Func specified as it's second argument (which accesses requested collection navigation), given the root entity (which now has include applied)
@maumar
Copy link
Contributor Author

maumar commented Jun 3, 2017

fixed in 0075cb7

thiennn added a commit to simplcommerce/SimplCommerce that referenced this issue Jul 6, 2017
* upgraded to netcore2preview2

* changed in ef core preview2

* ef core changed dotnet/efcore#8584

* correct user/role model
remove Microsoft.VisualStudio.Web.CodeGeneration.Design from WebHost because of warnings

* corret the type of select expression Expression<Func<TModel, TResult>>

* remove redundant Includes

* Remove PackageTargetFallback(deprecated)

* update readme, dockerfile
@ajcvickers ajcvickers modified the milestones: 2.0.0-preview2, 2.0.0 Oct 15, 2022
bruslega added a commit to elsashop/SimplCommerce that referenced this issue Aug 22, 2023
* upgraded to netcore2preview2

* changed in ef core preview2

* ef core changed dotnet/efcore#8584

* correct user/role model
remove Microsoft.VisualStudio.Web.CodeGeneration.Design from WebHost because of warnings

* corret the type of select expression Expression<Func<TModel, TResult>>

* remove redundant Includes

* Remove PackageTargetFallback(deprecated)

* update readme, dockerfile
polarisjrex0406 added a commit to polarisjrex0406/SimplCommerce that referenced this issue Apr 19, 2024
* upgraded to netcore2preview2

* changed in ef core preview2

* ef core changed dotnet/efcore#8584

* correct user/role model
remove Microsoft.VisualStudio.Web.CodeGeneration.Design from WebHost because of warnings

* corret the type of select expression Expression<Func<TModel, TResult>>

* remove redundant Includes

* Remove PackageTargetFallback(deprecated)

* update readme, dockerfile
auroravirtuoso added a commit to auroravirtuoso/e-commerce-system-dotnet that referenced this issue Jul 7, 2024
* upgraded to netcore2preview2

* changed in ef core preview2

* ef core changed dotnet/efcore#8584

* correct user/role model
remove Microsoft.VisualStudio.Web.CodeGeneration.Design from WebHost because of warnings

* corret the type of select expression Expression<Func<TModel, TResult>>

* remove redundant Includes

* Remove PackageTargetFallback(deprecated)

* update readme, dockerfile
frank-verynice added a commit to frank-verynice/e-commerce-system-dotnet that referenced this issue Nov 29, 2024
* upgraded to netcore2preview2

* changed in ef core preview2

* ef core changed dotnet/efcore#8584

* correct user/role model
remove Microsoft.VisualStudio.Web.CodeGeneration.Design from WebHost because of warnings

* corret the type of select expression Expression<Func<TModel, TResult>>

* remove redundant Includes

* Remove PackageTargetFallback(deprecated)

* update readme, dockerfile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

No branches or pull requests

2 participants