如何按 Entity Framework 中导航属性的字段进行过滤?
How to filter by fields from navigation properties in Entity Framework?
我 类 喜欢:
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
}
现在我想执行查询,使用 Entity Framework 获取所有产品,并预先加载特定的 ProductCategoryID:
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();
}
我认为我应该在 Where 子句中键入类似于 .Where(x => descentantIds.Contains(x.ProductsInCategories.ProductCategoryID))
的内容,但这行不通。
Here 是类似的解决方案,但我不知道如何在我的案例中应用它。
感谢您的任何建议!
试试这个
.SelectMany(x => x.ProductsInCategories.Where(c => descentantIds.Contains(c.ProductCategoryID))).Select(c => c.Product).Distinct()
虽然@mariovalens 提供了解决我的问题的有效解决方案,但我找到了另一个。我正在粘贴他们两个。这可能对其他人有帮助 ;)
请注意,对于正确的预加载插入 .Include() 方法后过滤方法,如 SelectMany()、Select()、Where() 等。在这些方法之前输入 .Include()方法将 return 导航属性中的空值。
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>();
}
我 类 喜欢:
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
}
现在我想执行查询,使用 Entity Framework 获取所有产品,并预先加载特定的 ProductCategoryID:
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();
}
我认为我应该在 Where 子句中键入类似于 .Where(x => descentantIds.Contains(x.ProductsInCategories.ProductCategoryID))
的内容,但这行不通。
Here 是类似的解决方案,但我不知道如何在我的案例中应用它。
感谢您的任何建议!
试试这个
.SelectMany(x => x.ProductsInCategories.Where(c => descentantIds.Contains(c.ProductCategoryID))).Select(c => c.Product).Distinct()
虽然@mariovalens 提供了解决我的问题的有效解决方案,但我找到了另一个。我正在粘贴他们两个。这可能对其他人有帮助 ;)
请注意,对于正确的预加载插入 .Include() 方法后过滤方法,如 SelectMany()、Select()、Where() 等。在这些方法之前输入 .Include()方法将 return 导航属性中的空值。
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>();
}