我的查询应该从数据库中检索产品类别信息并填充viewmodel ViewModelProductCategory
。这些类别将以递归方式排列在树形结构中,每个类别都有一个产品列表。此外,还有一个没有任何类别参考的产品列表,即所谓的孤儿产品。
当查询到达.Select(v => ...
时,出现问题,并且" ArgumentNullException:Value不能为null"扔了:
var VMCategories = _context.ProductCategories
.Include(e => e.Children).ToList()
.OrderBy(s => s.SortOrder)
.Where(r => r.ParentId == null) // only need root level categories
.Select(v => new ViewModelProductCategory
{
Id = v.Id,
Children = v.Children,
ParentId = v.ParentId,
Title = v.Title,
SortOrder = v.SortOrder,
// Get all orphan products (products without category):
OrphanProducts = v.ProductInCategory
.Where(o => !_context.ProductsInCategories.Any(pc => o.Id == pc.ProductId))
.Select(orph => new ViewModelProduct
{
Id = orph.Product.Id,
Title = orph.Product.Title,
Price = orph.Product.Price,
Info = orph.Product.Info,
SortOrder = orph.SortOrder
})
.OrderBy(s => s.SortOrder)
.ToList()
})
.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; }
public ProductCategory ParentCategory { get; set; } //nav.prop to parent
public ICollection<ProductCategory> Children { get; set; } //nav. prop to children
public List<ProductInCategory> ProductInCategory { 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; }
public List<ProductInCategory> InCategories { get; set; } // Nav.prop. to occurances in product categories
}
catgegory中产品的实体模型:
public class ProductInCategory
{
public int Id { get; set; }
public int ProductId { get; set; }
public int SortOrder { get; set; }
public int ProductCategoryId { get; set; }
public Product Product { get; set; } // Nav.prop. to product
public ProductCategory ProductCategory { get; set; } // Nav.prop. to category
}
产品类别的Viewmodel:
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 ProductCategory ParentCategory { get; set; } // Nav.prop. to parent
public IEnumerable<ProductCategory> Children { get; set; } // Nav.prop. to children
public List<ViewModelProduct> Products { get; set; } // Products in this category
public List<ViewModelProduct> OrphanProducts { get; set; } // Products with no references in ProductInCategory
}
具有类别标题的产品类别的Viewmodel(用于在产品视图中显示类别标题):
public class ViewModelCategoryWithTitle
{
public int Id { get; set; }
public string Title { get; set; }
}
产品的Viewmodel:
public class ViewModelProduct
{
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public int SortOrder { get; set; }
public IEnumerable<ViewModelCategoryWithTitle> Categories { get; set; }
}
附录
我忘了添加视图。首先,将模型发送到Index-view,如下所示:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
@Html.Partial("_CategoryRecursive", Model)
</ul>
然后Index-view调用这个递归的razor-view:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
@if (Model != null)
{
foreach (var item in Model)
{
<li>
<ul>
@Html.Partial("_CategoryRecursive.cshtml", item.Children)
</ul>
</li>
}
}
</ul>
答案 0 :(得分:0)
我认为评论者对于分解它是正确的。显然我没有你的数据就无法测试它,但我最初会尝试这样的事情:
var cpics = _context.ProductsInCategories;
var vmc = from pc in _context.ProductCategories
where pc.ParentId == null
orderby pc.SortOrder
select new ViewModelProductCategory(pc, cpics);
public class ViewModelProduct
{
public int Id { get; set; }
public string Title { get; set; }
public string Info { get; set; }
public decimal Price { get; set; }
public int SortOrder { get; set; }
public IEnumerable<ViewModelCategoryWithTitle> Categories { get; set; }
public ViewModelProduct(ProductInCategory pic)
{
Id = pic.Product.Id;
Title = pic.Product.Title;
Price = pic.Product.Price;
Info = pic.Product.Info;
SortOrder = pic.SortOrder;
}
public ViewModelProduct() { }
}
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 =>
Products != null && Products.Any() ? Products.Count().ToString() : "0";
public ProductCategory ParentCategory { get; set; } // Nav.prop. to parent
public IEnumerable<ProductCategory> Children { get; set; } // Nav.prop. to children
public List<ViewModelProduct> Products { get; set; } // Products in this category
public List<ViewModelProduct> OrphanProducts { get; set; } // Products with no references in ProductInCategory
public ViewModelProductCategory(ProductCategory pc, IEnumerable<ProductInCategory> cpics)
{
Id = pc.Id;
Children = pc.Children;
ParentId = pc.ParentId;
Title = pc.Title;
SortOrder = pc.SortOrder;
OrphanProducts = (from pcpic in pc.ProductInCategory
join cpic in cpics
on pcpic.Id equals cpic.ProductId
into pics
from pic in pics.DefaultIfEmpty()
where pic == null
select new ViewModelProduct(pcpic))
.OrderBy(s => s.SortOrder)
.ToList();
}
public ViewModelProductCategory() { }
}
检查空item.Children
:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
@if (Model != null)
{
@foreach (var item in Model)
{
@if (item.Children != null)
{
<li>
<ul>
@Html.Partial("_CategoryRecursive.cshtml", item.Children)
</ul>
</li>
}
}
}
</ul>
可能有太多的@ - 我不太使用MVC。