MVC заполняет модель иерархией

#c# #asp.net-mvc

#c# #asp.net-mvc

Вопрос:

У меня есть модель: List<PROJECT>

PROJECT -> наличие List<TASK>

TASK -> Наличие List<SUBTASK>

Данные будут заполняться из таблиц Project, Task, Subtask соответственно со ссылкой на каждую.

Каков эффективный способ заполнения этой модели с помощью разбивки на страницы?

Что я реализую:

  1. Выберите проект (первый вызов процедуры возвращает 10 записей проекта (отображается 10 записей))
  2. Выберите список задач на основе идентификатора проекта (вторая процедура вызывается 10 раз, чтобы перенести список задач в раздел проекты)
  3. Выберите список подзадач на основе идентификатора задачи (третья процедура вызывается несколько раз, чтобы вывести список подзадач в разделе задачи)

Это решение работает нормально, но требует нескольких вызовов базы данных.

Обновить

  public List<Project> GetProject(int page=1, int pageSize=10)
    {
        List<Project> _lstProject = new List<Project>();
        try
        {
            using (DevEntities db = new DevEntities())
            {
                _lstProject = db.ProjectSelect(page, pageSize).Select(m => new Project()
                {
                    ProjectId = m.ProjectID,
                    ProjectNumber = m.ProjectNo,
                    TaskList = GetTaskDetails(m.ProjectID)

                }).ToList();

            }
            return _lstProject ;
        }
        catch (Exception e)
        {
            throw;
        }

        finally
        {
            _lstProject = null;
        }
    }

public List<Task> GetTaskDetails(ProjectID)
    {
        List<Task> _lstTask = new List<Task>();
        try
        {
            using (DevEntities db = new DevEntities())
            {
                _lstTask = db.TaskSelect(ProjectID).Select(m => new Task()
                {
                    TaskId = m.TaskID,
                    TaskNumber = m.TaskNo,
                    SubTaskList = GetSubTaskDetails(m.TaskID)

                }).ToList();

            }
            return _lstTask ;
        }
        catch (Exception e)
        {
            throw;
        }

        finally
        {
            _lstTask = null;
        }
    }

public List<SubTask> GetSubTaskDetails(int TaskID)
    {
        List<SubTask> _lstSubTask = new List<SubTask>();
        try
        {
            using (DevEntities db = new DevEntities())
            {
                _lstSubTask = db.TaskSelect(TaskID).Select(m => new SubTask()
                {
                    SubTaskId = m.SubTaskID,
                    SubTaskNumber = m.SubTaskNo
                }).ToList();

            }
            return _lstSubTask ;
        }
        catch (Exception e)
        {
            throw;
        }

        finally
        {
            _lstSubTask = null;
        }
    }
  

Комментарии:

1. Не могли бы вы просто немного увеличить яркость вашего экрана? Немного сложно увидеть любой код, который у вас уже есть…

2. Когда вы получите эти 10 проектов, вы также можете заполнить задачи и подзадачи для этих проектов. Это означает один запрос на каждые 10 проектов. Как вы получаете доступ к своей базе данных? Используете ли вы ADO, EF, NHibernate?

3. используете ли вы entity framework в качестве ORM?

4. ДА, используя EF для доступа к БД

5. обновлен вопрос @GeoffJames. Это видно сейчас?

Ответ №1:

На мой взгляд, для оптимизации вашего кода у вас есть два допустимых варианта:

Вариант 1:

Один запрос для каждого типа объекта (всего 3 запроса):

 var projects = db.Projects.Where().Order().Skip().Take().Select().ToList(); // 1 query
var projectIds = projects.Select(x => x.ProjectId).ToList();

var tasks = db.Tasks.Where(x => projectIds.Contains(x.ProjectId)).Select().ToList(); // 1 query
var taskIds = tasks.Select(x => x.Id).ToList();

var subtasks = db.Tasks.Where(x => taskIds.Contains(x.TaskId)).Select().ToList() // 1 query

foreach(var project in projects)
{
    project.Tasks = tasks.Where(x => x.ProjectId == project.ProjectId).ToList();

    // etc
    // complete hierarchy structure
}
  

Вариант 2:

Один запрос с 2 левыми внешними соединениями:

 var projects = (from proj in db.Projects.Where()

                join t in db.Tasks on t.ProjectId equals proj.ProjectId into tasks
                from task in t.DefaultIfEmpty()

                join s in db.Tasks on s.TaskId equals task.Id into subtasks
                from subtask in subtasks.DefaultIfEmpty()

                select new 
                {
                    ProjectId = proj.ProjectId,
                    TaskId = task.Id,
                    SubtaskId = subtask.Id

                }).ToList(); // 1 query

// etc
// proceed with creating hierarchy structure using GroupBy
  

Какой из этих двух более эффективен?

Это зависит. Я уверен, что есть много людей, которые предпочитают одно другому, и я был бы рад услышать их комментарии.

Мой личный опыт научил меня обычно выбирать вариант 1, но вы должны протестировать и рассчитать оба из них в зависимости от объема ваших данных и конфигурации БД (индексы, fks) и решить для себя