I have classes like:
public class ProductInCategory
{
public Guid Guid { get; set; }
public long ProductID { get; set; }
public long ProductCategoryID { get; set; }
public virtual Product Product { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
}
public class Product
{
public virtual ICollection<ProductInCategory> ProductsInCategories { get; set; }
// and other fields and navigation properties not important for this example
}
And now I want to execute query which gets all products using Entity Framework with eager loading with specific ProductCategoryID's:
using (var db = new EntityDataModel())
{
var node = db.Tree.FirstOrDefault(x => x.Guid == editedNode);
List<long> descentantIds = db.Tree
.Where(x => x.AncestorID == node.AncestorID)
.Select(x => x.DescendantID).ToList();
List<Product> products = db.Products
.Include("Details")
.Include("Prices")
.Include("Prices.Currency")
.Include("Prices.Seller")
.Include("Translations")
.Include("Translations.Language")
.Include("ProductsInCategories")
.Where(x => ... )) // how to filter by ProductsInCategories.ProductCategoryID (which in my case is descentantIds) ?
.ToList();
}
I think that I should to type in Where clause something similar to .Where(x => descentantIds.Contains(x.ProductsInCategories.ProductCategoryID))
, but this won't work.
Here is similar solution, but I don't know how to apply it in my case.
Thank you for any advice!
Try this
.SelectMany(x => x.ProductsInCategories.Where(c => descentantIds.Contains(c.ProductCategoryID))).Select(c => c.Product).Distinct()
Although @mariovalens gave working solution which solved my issue I found another one. I'm pasting both of them. It might be helpful for others ;)
Note that for proper eager loading insert .Include() methods after filtering methods like SelectMany(), Select(), Where() etc. Inputing .Include() before those methods will return null values in navigation properties.
using (var db = new EntityDataModel())
{
var node = db.Tree.FirstOrDefault(x => x.Guid == editedNode);
List<long> descentantIds = db.Tree
.Where(x => x.AncestorID == node.AncestorID)
.Select(x => x.DescendantID)
.ToList();
List<Product> method1 = db.Products
.SelectMany(x => x.ProductsInCategories.Where(c => descentantIds.Contains(c.ProductCategoryID))).Select(c => c.Product).Distinct()
.Include(c => c.Assets.Select(c1 => c1.Translations.Select(c2 => c2.Language)))
.Include(c => c.Tags.Select(c1 => c1.Translations.Select(c2 => c2.Language)))
.Include(c => c.Details)
.Include(c => c.Prices.Select(c1 => c1.Currency))
.Include(c => c.Prices.Select(c1 => c1.Seller))
.Include(c => c.Translations.Select(c1 => c1.Language))
.Include(c => c.ProductsInCategories)
.ToList();
var method2 = (from product in db.Products
join productsInCategories in db.ProductsInCategories
on product.ID equals productsInCategories.ProductID
join productsCategories in db.ProductsCategories
on productsInCategories.ProductCategoryID equals productsCategories.ID
where descentantIds.Contains(productsInCategories.ProductCategoryID)
select product)
.Include(c => c.Assets.Select(c1 => c1.Translations.Select(c2 => c2.Language)))
.Include(c => c.Tags.Select(c1 => c1.Translations.Select(c2 => c2.Language)))
.Include(c => c.Details)
.Include(c => c.Prices.Select(c1 => c1.Currency))
.Include(c => c.Prices.Select(c1 => c1.Seller))
.Include(c => c.Translations.Select(c1 => c1.Language))
.Include(c => c.ProductsInCategories);
var result = method2.ToList<Product>();
}