Комплексная группировка по внукам

1

У меня сложный запрос LINQ, который я изо всех сил пытаюсь понять. У меня есть такая модель домена:

ReviewCategory > has ReviewQuestions > has ReviewAnswers

То, что я пытаюсь сделать, - вычислить количество ответов на определенное значение для всех вопросов в категории. Я строю из очень старой классической системы asp, которая использует несколько хранимых процедур базы данных, чтобы это сделать, но я думаю, что это можно управлять с помощью LINQ to EF.

У меня есть ViewModel, что я устанавливаю имя категории, порядок и счетчик для каждого значения ответа, поэтому модель представления будет содержать список категорий и расчеты количества ответов.

Вот код, на который я застрял:

pcvm.Categories = from x in _repository.GetAll<ReviewCategory>()
                  where x.include == true &&
                       ((x.AuditQuestionGroupId != null ? x.AuditQuestionGroupId : 0) == this.LoggedInEntity.AuditQuestionGroupId)
                  from y in x.Questions
                  where y.include == true
                  from z in y.Answers
                  where z.entityId == this.LoggedInEntity.EntityId
                  orderby x.order != null ? 999 : x.order, x.name
                  group x by new { x.id, x.name, x.order, z.yourEvaluation, z.yourResponse } into newGroup
                  select new PracticeConductCategoriesViewModel
                  {
                      Id = newGroup.Key.id, // The categoryId
                      Name = newGroup.Key.name, // The category name
                      Order = newGroup.Key.order, // The category order
                      EvaluationNR = newGroup.Key.yourEvaluation, // The number of answers where yourEvaluation = 0
                      Evaluation1 = newGroup.Key.yourEvaluation, // The number of answers where yourEvaluation = 1 etc etc.
                      Evaluation2 = newGroup.Key.yourEvaluation,
                      Evaluation3 = newGroup.Key.yourEvaluation,
                      Evaluation4 =  newGroup.Key.yourEvaluation,
                      Percentage = newGroup.Key.yourEvaluation // Percentage of yourEvaluations answered for each category
                   };
  1. Поэтому, по сути, я пытаюсь группировать суммы по значениям внуков. Я добавил в комментарии значения, которые я пытаюсь вернуть в ViewModel, но я не могу понять, как сделать подсчет ответов. Должны ли ответы быть в группе или они должны быть в другом запросе после этой группировки? Если да, то как мне использовать переменную z после группы.

  2. Я получаю неправильный список категорий, поскольку я получаю только категории, на которые есть ответы. Но я знаю, что могу использовать из/в /isdefault, поэтому, пожалуйста, не беспокойтесь об этом.

Теги:
linq
group-by
entity-framework-6
linq-to-entities

2 ответа

0
Лучший ответ

Это оптимизированная версия вышеуказанного ответа.

var categories = (from x in _repository.GetAll<ReviewCategory>()
                              from y in x.Questions
                              where y.include == true && x.include == true &&
                                  ((x.AuditQuestionGroupId != null ? x.AuditQuestionGroupId : 0) == this.LoggedInEntity.AuditQuestionGroupId)
                              group x by new { category = x } into newGroup
                              select new ConductCategoriesViewModel
                              {
                                  Id = newGroup.Key.category.id,
                                  name = newGroup.Key.category.name,
                                  order = newGroup.Key.category.order != null ? newGroup.Key.category.order : 999,
                                  Evaluation1 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourEvaluation == 1 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Evaluation2 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourEvaluation == 2 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Evaluation3 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourEvaluation == 3 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Evaluation4 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourEvaluation == 4 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  EvaluationNR = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourEvaluation == 0 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Response1 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourResponse == 1 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Response2 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourResponse == 2 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  Response3 = newGroup.Key.category.Questions.SelectMany(a => a.Answers)
                                                .Count(b => b.Question.radioDisplay == true && b.Question.include == true && b.yourResponse == 3 && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true),
                                  QuestionsAnswered = newGroup.Key.category.Questions.SelectMany(x => x.Answers)
                                                .Count(b => b.yourEvaluation != null && b.entityId == this.LoggedInEntity.EntityId && b.entityLevelAudit == true && b.Question.include == true && b.Question.radioDisplay == true),
                                  TotalQuestions = newGroup.Key.category.Questions.Count(x => x.include == true && x.radioDisplay == true) == 0 ? 0 : newGroup.Key.category.Questions.Count(x => x.include == true && x.radioDisplay == true)
                              })
                                .OrderBy(x => x.order != null ? x.order : 999).ThenBy(x => x.name) // It doesn't sort properly if this is in the linq query for some reason.
                               .ToList();
            return categories;
0

Я понял это (мой мозг почти взорвался, делая это). Мне потребовалось некоторое время, чтобы понять, что, поскольку у меня не было вопросов или ответов в группе (иначе они бы не группировались по категориям), мне пришлось передать весь объект категории в выбранный новый, а затем доступ к внукам (ответы другим подзапросом) таким образом.

Вот рабочий код:


PracticeConductViewModel pcvm = new PracticeConductViewModel();
            pcvm.Categories = (from x in _repository.GetAll<ReviewCategory>()
                               where x.include == true &&
                               ((x.AuditQuestionGroupId != null ? x.AuditQuestionGroupId : 0) == this.LoggedInEntity.AuditQuestionGroupId)
                               from y in x.Questions
                               where y.include == true                               
                               group x by new { x, x.id, x.name, x.order } into newGroup
                               orderby newGroup.Key.order != null ? 999 : newGroup.Key.order, newGroup.Key.name
                               select new PracticeConductCategoriesViewModel
                               {
                                   Id = newGroup.Key.id, // The categoryId
                                   name = newGroup.Key.name, // The category name
                                   order = newGroup.Key.order, // The order
                                   Evaluation1 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourEvaluation == 1 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Evaluation2 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourEvaluation == 2 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Evaluation3 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourEvaluation == 3 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Evaluation4 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourEvaluation == 4 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   EvaluationNR = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourEvaluation == 0 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Response1 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourResponse == 1 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Response2 = (from a in newGroup.Key.x.Questions
                                                  from b in a.Answers
                                                  where b.yourResponse == 2 && b.entityId == this.LoggedInEntity.EntityId
                                                  select a).Count(),
                                   Response3 = (from a in newGroup.Key.x.Questions
                                                from b in a.Answers
                                                where b.yourResponse == 3 && b.entityId == this.LoggedInEntity.EntityId
                                                select a).Count(),
                                   //Percentage = newGroup.Key.yourEvaluation // Percentage of yourEvaluations answered for each question
                               })
                               .ToList();


            return View(pcvm);

Этот ответ работает, но есть ли способ оптимизировать этот код?

  • 0
    Попробуйте использовать .Count(x => bla) вместо .Where(x => bla).Count() .
  • 0
    Как бы я сделал это в запросе linq?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню