#c# #asp.net-mvc
#c# #asp.net-mvc
Вопрос:
У меня есть модель: List<PROJECT>
PROJECT
-> наличие List<TASK>
TASK
-> Наличие List<SUBTASK>
Данные будут заполняться из таблиц Project, Task, Subtask соответственно со ссылкой на каждую.
Каков эффективный способ заполнения этой модели с помощью разбивки на страницы?
Что я реализую:
- Выберите проект (первый вызов процедуры возвращает 10 записей проекта (отображается 10 записей))
- Выберите список задач на основе идентификатора проекта (вторая процедура вызывается 10 раз, чтобы перенести список задач в раздел проекты)
- Выберите список подзадач на основе идентификатора задачи (третья процедура вызывается несколько раз, чтобы вывести список подзадач в разделе задачи)
Это решение работает нормально, но требует нескольких вызовов базы данных.
Обновить
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) и решить для себя