Вот небольшое консольное приложение, которое, я думаю, демонстрирует, как получить иерархическую группировку, которую вы ищете:
internal class Program
{
public class Module
{
public int ModuleID { get; set; }
public List<Group> Groups { get; set; }
}
public class Group
{
public int GroupID { get; set; }
public int ModuleID { get; set; }
public List<Question> Questions { get; set; }
}
public class Question
{
public int ModuleID { get; set; }
public int GroupID { get; set; }
public int QuestionID { get; set; }
}
private static void Main(string[] args)
{
var questions = new List<Question>();
questions.Add(new Question {ModuleID = 1, GroupID = 1, QuestionID = 1});
questions.Add(new Question {ModuleID = 2, GroupID = 1, QuestionID = 2});
questions.Add(new Question {ModuleID = 3, GroupID = 2, QuestionID = 3});
questions.Add(new Question {ModuleID = 4, GroupID = 4, QuestionID = 4});
var groups = questions
.GroupBy(q => new {q.GroupID, q.ModuleID})
.Select(qg => new Group
{
GroupID = qg.Key.GroupID,
ModuleID = qg.Key.ModuleID,
Questions = qg.ToList()
})
.GroupBy(g => g.ModuleID)
.Select(gg => new Module
{
ModuleID = gg.Key,
Groups = gg.ToList()
})
.ToList();
}
}
Самая важная строка здесь, вероятно, .GroupBy(q => new {q.GroupID, q.ModuleID})
. Группирования по GroupId
недостаточно, потому что мы также должны учитывать, находятся ли Вопросы в разных модулях. Например, в примере вышеупомянутых тестовых данных это всплыло бы из-за ошибочной группировки вопросов № 1 и № 2, потому что они оба имеют одинаковые значения GroupID
, игнорируя тот факт, что они находятся в разных модулях. Чтобы решить эту проблему, мы создаем новый анонимный объект, связывающийся с GroupID
и ModuleID
вопроса (new {q.GroupID, q.ModuleID})
), и вместо этого группируем этот анонимный объект.