从自引用表中选择并转换为视图模型
本文关键字:转换 视图 模型 选择 自引用 | 更新日期: 2023-09-27 18:36:31
如何
选择自引用表的所有级别作为视图模型。 如果最大级别是 2 或 3,那么我可以通过多次调用Select
来做到这一点,但我有 4-5 级菜单,我认为应该有更好的解决方案来做到这一点并选择所有级别。
这是我的视图模型:
public class MenuViewModel
{
public MenuViewModel()
{
Childs = new HashSet<MenuViewModel>();
}
public int Id{ get; set; }
public string Title { get; set; }
public string Url { get; set; }
public ICollection<MenuViewModel> Childs { get; set; }
}
这是我的菜单类:
public class Menu
{
public Menu()
{
Childs = new HashSet<Menu>();
}
public int Id{ get; set; }
public string Title { get; set; }
public string Url { get; set; }
public string Description { get; se; }
public byte[] Icon { get; set; }
public int Order { get; set; }
public ICollection<Menu> Childs { get; set; }
}
var viewModel = _dataContext.Menus
.Select(x => new MenuViewModel
{
Id = x.Id,
Title = x.Title,
Child = ???
}
.ToList();
使用 EF 时,可以按以下方式执行以下操作:
public class BlogComment
{
public int Id { set; get; }
[MaxLength]
public string Body { set; get; }
public virtual BlogComment Reply { set; get; }
public int? ReplyId { get; set; }
public ICollection<BlogComment> Children { get; set; }
}
using (var ctx = new MyContext())
{
var list = ctx.BlogComments
//.where ...
.ToList() // fills the childs list too
.Where(x => x.Reply == null) // for TreeViewHelper
.ToList();
}
通过这种方式,您不需要使用递归查询,但据我所知,当使用视图模型获取数据时,EF的动态代理被破坏了。
关于上面的例子:只需选择一个评论列表,然后
.Where(x=>x.Reply==null).Tolist()
EF 填充注释的子属性。
参考
假设Id
属性是唯一的,你可以分两次完成:
- 创建不带子项但具有关联子项 ID 的视图模型项。从该数据中创建字典,该字典将允许您按其 id 获取任何视图模型。此字典中的值将是创建的视图模型及其子 ID 。
- 对于每个视图模型项,使用子 ID 获取关联的视图模型项。
像这样:
var tempModels = _dataContext
.Menus
.Select(menu => new
{
childrenIds = menu.Childs.Select(item => item.Id).ToArray(),
viewModel =
new MenuViewModel
{
Id = menu.Id,
Title = menu.Title
}
})
.ToDictionary(
keySelector: item => item.viewModel.Id);
var viewModels = tempModels
.Select(kv =>
{
var viewModel = kv.Value.viewModel;
viewModel.Childs = kv
.Value
.childrenIds
.Select(childId =>
tempModels[childId].viewModel)
.ToList();
return viewModel;
})
.ToList();
对于深度问题,您可以在模型中使用一个像 Depth 这样的 int 属性,然后您可以获取如下数据:
public class BlogComment
{
public int Id { set; get; }
[MaxLength]
public string Body { set; get; }
public int Depth{get;set}
public virtual BlogComment Reply { set; get; }
public int? ReplyId { get; set; }
public ICollection<BlogComment> Children { get; set; }
}
using (var ctx = new MyContext())
{
var list = ctx.BlogComments
.Where(a=>a.Depth<2)
.ToList() // fills the childs list too
.Where(x => x.Reply == null) // for TreeViewHelper
.ToList();
}
为了在这个Senario中使用视图模型,我使用自动映射器进行测试,但是当使用viewModel选择数据时,EF生成的动态代理被销毁。
请注意此问题