Allow fetching navigation properties when using projections via Include(...) #599
Labels
closed-fixed
The issue has been fixed and is/will be included in the release indicated by the issue milestone.
type-unknown
Milestone
In EF6 it is a known limitation that the Include("...") methods will be ignored as soon as the query contains a projection.
According to the following issue this behaviour is by design: https://connect.microsoft.com/VisualStudio/feedback/details/347543/entity-framework-eager-loading-not-working-in-some-projection-scenarios
Generally I agreee that this behaviour is "the right" one and makes perfect sense for many use cases.
However in our application it is a real limitation for some scenarios, so I am going to explain why "Include with Projections" would make sense for us.
We are currently developing a very large LOB application (CRM) for a customer using EF6. This application has the following characteristics:
Especially because of combination of 1+2+4 we are avoiding DTOS and are-reusing our entities everywhere possible. In a large project with so many entities, DTOs add a remarkable level of (extra) complexity and work (code) to do and this is something we want to avoid.
See also: "Pros and Cons of Data Transfer objects": http://msdn.microsoft.com/en-us/magazine/ee236638.aspx
In this rich-client application, we are heavily using a third party grid component from DevExpress. The nice thing about this grid is that it allows you to just pass an IQueryable source to the grid, and based on this source the grid allows you to perform all sort of operations. That means that grouping, filtering, sorting and all of these operations, even in combination, are possible for the end-user, and there is zero application code required. So this is a very powerful story.
This huge flexibility for the end-user is one of the key-feature of this application.
So let me explain how this generic displaying of entities in grids usually works.
Lets consider the following simple Entity:
In the grid, this would be displayed the following way:
[Name] | [Country.Name] | [CreationUser.Name]
With the Include(...) extension method this is fairly easy. For each Navigation-Property which is currently visible in the grid, we dynamically generate an include for this property.
So if the user is viewing the customer grid and only has the "Country" Navigation-Property enabled, we can dynamically generate the following query:
As soon as the user adds the "CreationUser" column to the grid the query get modified to:
This allows us to use our entities in Grids, without creating a DTO object and manually projecting each property. Considering the huge amount of entities we have this saves lots of lots of duplicate code (not only properties, but also attributes etc.)
However, sometimes there are scenarios where we need additional data in our grids which cannot be retrieved from a property (e.x query the comment count for an entity).
If this is the case, we have to create a List-Model and specify the additional properties:
In the grid this would be displayed the following way:
[Customer.Name] | [Customer.Country.Name] | [Customer.CreationUser.Name] | [CommentCount]
Now, ideally, I would like to write the query this way:
However, because Include(..) statements are ignored as soon as Projections are used, the Country and CreationUser Navigation-Property is no longer included within the query.
A way to make this work atm is by adding all Navigation-Properties of the Customer entity to the projecting list model.
and then include it in the projection:
This has a lots of drawbacks:
Hopefully I could make my point why we would really benefit from being able to include navigation-properties when using projections.
Maybe EF7 could provide an API for forced Navigation-Property includes?
Probably EF7 could just provide an overload to force includes?
What are your thoughts? I would be really happy to get some feedback. Is it possible to consider this requirement in your design of EF7 to make it possible?
looking forward,
best regards,
David
The text was updated successfully, but these errors were encountered: