从自引用表中选择并转换为viewmodel

时间:2016-02-28 09:08:38

标签: c# entity-framework linq linq-to-entities entity-framework-6

如何选择自引用表的所有级别作为视图模型。如果最高等级是2或3然后我可以通过多次调用Select来做到这一点,但我有4-5级菜单,我认为应该有更好的解决方案,并选择所有级别。

这是我的viewmodel:

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();

3 个答案:

答案 0 :(得分:1)

当您使用EF时,您可以采取以下方式:

3

通过这种方式你不需要使用递归查询但据我所知,当使用视图模型获取数据时,EF的动态代理被破坏。

关于上述示例: 只需选择一个评论列表并使用

public class QSort {

    public static void quickSort(int[] arr, int left, int right){
        int i = left;
        int j = right;
        int temp;
        int pivot = arr[(left+right)/2];
        System.out.println("\n\nleft = " + left + "\tright = " + right);
        System.out.println("Pivot is: " + pivot + "(" +  (left+right)/2 + ")");
        while(i <= j){
            while(arr[i] < pivot){
                System.out.println("i is: " + arr[i] + "(" + i + ")");
                i++;
                System.out.println("i is: " + arr[i] + "(" + i + ")");
            }
            while(arr[j] > pivot){
                System.out.println("j is: "+ arr[j] + "(" + j + ")");
                j--;
                System.out.println("j is: "+ arr[j] + "(" + j + ")");
            }
            if(i <= j){
                System.out.println("i is: " + arr[i] + "(" + i + ")");
                System.out.println("j is: "+ arr[j] + "(" + j + ")");
                System.out.println("Swapped " + arr[i] + "(" + i + ")"+ " with " + arr[j] + "(" + j + ")");
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
                j--;
                System.out.println("i is: (" + i + ")");
                System.out.println("j is: (" + j + ")");
                System.out.println("Pivot is: " + pivot + "(" +  (left+right)/2 + ")");
            }
        }
        if(left < j){
            System.out.println("j is: (" + j + ")");
            quickSort(arr, left, j);
        }
        if(i < right){
            System.out.println("i is: (" + i + ")");
            quickSort(arr, i, right);
        }
    }

    public static void display(int[] arr){
        if(arr.length > 0){
            System.out.print(arr[0]);
        }
        for(int i = 1; i < arr.length; i++){
            System.out.print(", " + arr[i]);
        }
    }

    public static void main(String[] args) {
        int[] data = new int[]{10,5,3,22,11,2};
        System.out.println("Before: ");
        display(data);
        quickSort(data, 0, data.length-1);
        System.out.println("\nAfter: ");
        display(data);
    }
}

EF填充评论的儿童属性。

Reference

答案 1 :(得分:0)

假设Id属性是唯一的,您可以通过两次传递:

  1. 创建没有子项的viewmodel项,但具有关联的子ID。从该数据创建Dictionary,允许您通过其id获取任何viewmodel。此字典中的值将是创建的视图模型及其子ID。
  2. 对于每个viewmodel项,使用子ID获取关联的视图模型项。
  3. 类似的东西:

    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();
    

答案 2 :(得分:0)

对于深度问题,您可以在模型中使用像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生成的动态代理将被销毁。

请注意this Issue