What seemed that it should be a relatively straight-forward task has turned into something of a surprisingly complex issue. To the point that I'm starting to think that my methodology perhaps is simply out of scope with the capabilities of Linq.
What I'm trying to do is piece-together a Linq query and then invoke .Include()
in order to pull-in values from a number of child entities. For example, let's say I have these entities:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public ISet<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
public string Name { get; set; }
}
And let's say I want to perform a query to retrieve records from Parent
, where Name
is some value and Location
is some other value, and then include Child
records, too. But for whatever reason I don't know the query values for Name
and Location
at the same time, so I have to take two separate queryables and join them, such:
MyDbContext C = new MyDbContext();
var queryOne = C.Parent.Where(p => p.Name == myName);
var queryTwo = C.Parent.Where(p => p.Location == myLocation);
var finalQuery = queryOne.Intersect(queryTwo);
That works fine, producing results exactly as if I had just done:
var query = C.Parent.Where(p => p.Name == myName && p.Location = myLocation);
And similarly, I can:
var finalQuery = queryOne.Union(queryTwo);
To give me results just as if I had:
var query = C.Parent.Where(p => p.Name == myName || p.Location = myLocation);
What I cannot do, however, once the Intersect()
or Union()
is applied, however, is then go about mapping the Child
using Include()
, as in:
finalQuery.Include(p => p.Children);
This code will compile, but produces results as follows:
- In the case of a
Union()
, a result set will be produced, but noChild
entities will be enumerated. - In the case of an
Intersect()
, a run-time error is generated upon attempt to applyInclude()
, as follows:
Expression of type 'System.Collections.Generic.IEnumerable`1[Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable`1[System.Object]' of method 'System.Collections.Generic.IEnumerable`1[System.Object] Intersect[Object](System.Collections.Generic.IEnumerable`1[System.Object], System.Collections.Generic.IEnumerable`1[System.Object])'
The thing that baffles me is that this code will work exactly as expected:
var query = C.Parent.Where(p => p.Name == myName).Where(p => p.Location == myLocation);
query.Include(p => p.Children);
I.e., with the results as desired, including the Child
entities enumerated.
A long time has gone by, but this
.Include
problem still exists in EF 6. However, there is a workaround: Append every child request with.Include
before intersecting/Unionizing.As stated by @Ivan Stoev, Intersection/Union is done with after-fetched data, while
.Include
is ok at request time.So, as of now, you have this one option available.