簡體   English   中英

從自引用表中選擇並轉換為viewmodel

[英]Select from self-referencing table and convert to viewmodel

如何選擇自引用表的所有級別作為視圖模型。 如果最大級別是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; }
}

這是我的Menu類:

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屬性是唯一的,則可以分兩步進行:

  1. 創建沒有子代但具有關聯子代ID的viewmodel項。 從該數據中創建Dictionary ,將允許您通過其ID獲取任何視圖模型。 該詞典中的值將是與其子代ID一起創建的viewmodel。
  2. 對於每個viewmodel項,使用子代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,我使用AutoMapper進行了測試,但是當使用viewModel選擇數據時,EF生成的動態代理將被銷毀。

請注意此問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM