[英]LINQ query to get recursive category structure and products of each category
如何重寫查詢以將每個類別的所有產品包括在遞歸產品類別樹中? 該查詢獲取類別及其子級,因此我只缺少產品:
var categories = _context.ProductCategories
.Include(e => e.Children)
.Where(e => e.ParentId == null)
.ToList();
實體模型:
public class ProductCategory
{
public int Id { get; set; }
public int SortOrder { get; set; }
public string Title { get; set; }
[ForeignKey(nameof(ParentCategory))]
public int? ParentId { get; set; }
// Nav.props:
public ProductCategory ParentCategory { get; set; }
public ICollection<ProductCategory> Children { get; set; }
public List<ProductInCategory> ProductInCategory { get; set; }
}
public class ProductInCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
public int ProductCategoryId { get; set; }
// Nav.props:
public Product Product { get; set; }
public ProductCategory ProductCategory { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
// Nav.props:
public List<ProductInCategory> InCategories { get; set; }
}
視圖模型:
public class ViewModelProductCategory
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
public string ProductCountInfo
{
get
{
return Products != null && Products.Any() ? Products.Count().ToString() : "0";
}
}
public ViewModelProductCategory ParentCategory { get; set; }
public IEnumerable<ViewModelProductCategory> Children { get; set; }
public IEnumerable<ViewModelProduct> Products { get; set; }
}
我正在使用AutoMapper將查詢結果轉換為viewmodel。
這是我嘗試渲染的方式:
索引視圖:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
@Html.Partial("_CategoryAndProductRecursive", Model)
</ul>
_CategoryAndProductRecursive.cshtml:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
@if (Model != null)
{
foreach (var item in Model)
{
<li>
@item.Title
<ul style="list-style:none;">
@Html.Partial("_CategoryAndProductRecursive.cshtml", item.Children)
@if (item.Products != null)
{
@foreach (var product in item.Products)
{
<li>@product.Title</li>
}
}
</ul>
</li>
}
}
</ul>
EF核心查詢部分實際上有兩個獨立的問題。
首先是如何急於加載ProductCategory.ProductInCategory
和ProductInCategory.Product
導航屬性。 答案很簡單-使用Include
/ ThenInclude`,如文檔的“ 加載相關數據 - 急切加載”部分所述。
第二個是如何為ProductCategory.Children
遞歸地執行該操作。 技巧是強制將整個 ProductCategory
樹加載到內存中,從而讓EF Core導航屬性fixup進行父/子實體鏈接, 然后過濾根實體。
var categories = _context.ProductCategories
.Include(e => e.ProductInCategory)
.ThenInclude(e => e.Product)
.AsEnumerable() // <-- Force full execution (loading) of the above
.Where(e => e.ParentId == null) // <-- then apply the root filter
.ToList();
請注意,在此過程中我們不需要包括Children
。 請注意,某些Children
集合將為null
。 如果這是一個問題,只需確保您在構造函數中或使用初始化程序初始化它們即可。
public ICollection<ProductCategory> Children { get; set; } = new List<ProductCategory>();
您可以嘗試使用Load而不是Include and loop進行預定義的次數來每次加載子代。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.