当我使用这个查询和实体模型时,事情正在发挥作用:
var categories = _context.ProductCategories.Include(e => e.Children).ToList();
var topLevelCategories = categories.Where(e => e.ParentId == null);
return View(topLevelCategories);
实体模型:
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; }
}
...但是当我尝试切换到使用viewmodel时,我收到此错误消息:
“InvalidOperationException:传递给ViewDataDictionary的模型项的类型为'System.Collections.Generic.HashSet 1[MyStore.Models.ProductCategory]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable
1 [MyStore.Models.ViewModels.ViewModelProductCategory]'。”
我知道发送到视图的模型不对,但我不明白为什么。
我的viewmodel查询:
var VMCategories = _context.ProductCategories
.Include(e => e.Children).ToList()
.OrderBy(s => s.SortOrder)
.Where(r => r.ParentId == null)
.Select(v => new ViewModelProductCategory
{
Id = v.Id,
Children = v.Children,
ParentId = v.ParentId,
Title = v.Title,
SortOrder = v.SortOrder
})
.ToList();
return View(VMCategories);
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 =>
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
}
索引视图:
@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
@Html.Partial("_CategoryRecursive", Model)
</ul>
_CategoryRecursive.cshtml:
@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>
我/我的错误在哪里?
答案 0 :(得分:1)
您的视图模型是实体模型和视图模型的混合和匹配。例如,视图模型Children集合是实体模型类型,同时它也应该是视图模型的集合。保持清洁,不要让实体模型泄漏到您的视图模型中
public class ProductCategoryVM
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int? Products { get; set; }
public IEnumerable<ProductCategoryVM> Children { get; set; }
}
一旦你有了这个
(知道有多个级别的类别)
var query = from category in context.Categories
let products = from product in context.Products
where product.CategoryId == category.Id
select product
select new ProductCategoryVM
{
Id = category.Id,
ParentId = category.ParentId,
Title = category.Title,
Products = products.Count(),
...
};
var viewmodels = query.ToList();
下一步可能是以root身份递归地将子项附加到相应的父项。 (查看gist了解整个情况)
var root = viewmodels
.Where(p => p.ParentId == null)
.FirstOrDefault();
root.Traverse(viewmodels);
public static class Extensions
{
public static void Traverse(this ProductCategoryVM node, IEnumerable<ProductCategoryVM> nodes)
{
var children = nodes.Where(p => p.ParentId == node.Id);
foreach (var child in children)
{
child.Traverse(nodes);
}
node.Children = children;
}
}