NOTE: This is Entity Framework 7 / Entity Framework Core running on DNX.
I have the following two models:
public class ProductTag
{
[Key]
public Guid Id { get; set; }
[Required]
public Guid TagId { get; set; }
public Tag Tag { get; set; }
[Required]
public Guid ProductId { get; set; }
public Product Product { get; set; }
}
public class Product
{
[Key]
public Guid Id { get; set; }
[Required]
public String Name { get; set; }
[Required]
public UInt32 Price { get; set; }
public List<ProductTag> Tags { get; set; } = new List<ProductTag>();
}
When I try to execute the following query, it fails to find any matches:
await _bagsContext.Products
.Where(product => expectedTagIds
.All(expectedTagId => product.Tags
.Select(productTag => productTag.TagId)
.Contains(expectedTagId)))
.ToListAsync();
Note: When I run the following query I get the full results, including the Tags!
await _bagsContext.Products.ToListAsync()
This suggests that it is the Where clause specifically that doesn't have the necessary things populated. Perhaps this is an issue (as suggested in the comments) of the Where clause being executed client side before the DB is queried for the Products.
The goal of the query is to return a list of products that have every expectedTagId
on them.
For a simple example take the two products
apple
- tags:fruit
,round
banana
- tags:fruit
,long
Given a call to the above code with expectedTagIds
for the tags fruit
and round
would only return apple
.
I managed to fix my issue and get the above query to work by adding the following line above the call.
Task.WaitAll(_bagsContext.ProductTags.LoadAsync(), _bagsContext.Products.LoadAsync());
I kind of understand why ProductTags
needs to be pulled in, I assume that LINQ to Entities doesn't drill deep enough into the Where clause to realize that it needs the tags when it compiles the query.
However, I can't fathom why I need to call LoadAsync()
on Products
. Products
is the table I am querying over.