using System.Collections.Generic;
public static void Main()
List<Group> _groups = new List<Group>();
List<CategoryRoot> _categoryRoots = new List<CategoryRoot>();
List<Category> _categories = new List<Category>();
_categories.Add(new Category { Id = 1, Name = "C 1", CategoryRoot_Id = 1 });
_categories.Add(new Category { Id = 2, Name = "C 2", CategoryRoot_Id = 1 });
_categories.Add(new Category { Id = 3, Name = "C 3", CategoryRoot_Id = 3 });
_categoryRoots.Add(new CategoryRoot { Id = 1, Name = "CR 1", Group_Id = 1, Categories = _categories.Where(p => p.CategoryRoot_Id == 1).ToList() });
_categoryRoots.Add(new CategoryRoot { Id = 2, Name = "CR 2", Group_Id = 1, Categories = _categories.Where(p => p.CategoryRoot_Id == 2).ToList() });
_categoryRoots.Add(new CategoryRoot { Id = 3, Name = "CR 3", Group_Id = 2, Categories = _categories.Where(p => p.CategoryRoot_Id == 3).ToList() });
_categoryRoots.Add(new CategoryRoot { Id = 4, Name = "CR 4", Group_Id = 3, Categories = _categories.Where(p => p.CategoryRoot_Id == 4).ToList() });
_groups.Add(new Group { Id = 1, Name = "Group A", CategoryRoots = _categoryRoots.Where(p => p.Group_Id == 1).ToList() });
_groups.Add(new Group { Id = 2, Name = "Group B", CategoryRoots = _categoryRoots.Where(p => p.Group_Id == 2).ToList() });
_groups.Add(new Group { Id = 3, Name = "Group C", CategoryRoots = _categoryRoots.Where(p => p.Group_Id == 3).ToList() });
_groups.Add(new Group { Id = 4, Name = "Group D", CategoryRoots = _categoryRoots.Where(p => p.Group_Id == 4).ToList() });
var results = (from g in _groups
join cr in _categoryRoots on g.Id equals cr.Group_Id into gcr
from lgc in gcr.DefaultIfEmpty(new CategoryRoot())
join c in _categories on lgc.Id equals c.CategoryRoot_Id into ccr
from lccr in ccr.DefaultIfEmpty()
CategoryRoot_Id = lgc == null ? 0: lgc.Id,
CategoryRootName = lgc == null ? "": lgc.Name,
Category_Id = lccr == null ? 0: lccr.Id,
CategoryName = lccr == null ? "": lccr.Name
foreach (var result in results)
Console.WriteLine("Id:{0} Name:{1} CR:{2} CRN:{3} C:{4} CName:{5}", result.Id, result.Name, result.CategoryRoot_Id, result.CategoryRootName, result.Category_Id, result.CategoryName);
Console.WriteLine("------------------------");
public class GroupCategory
public int Id { get; set; }
public string Name { get; set; }
public int CategoryRoot_Id { get; set; }
public string CategoryRootName { get; set; }
public int Category_Id { get; set; }
public string CategoryName { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<CategoryRoot> CategoryRoots { get; set; }
public class CategoryRoot
public int Id { get; set; }
public string Name { get; set; }
public int Group_Id { get; set; }
public Group Group { get; set; }
public IEnumerable<Category> Categories { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public int CategoryRoot_Id { get; set; }
public CategoryRoot CategoryRoot { get; set; }