Курс Обучения. Загрузка Данных Из Entity Framework В Приложение Asp.net Mvc

Это продолжение серии статей, посвященных разработке с использованием Entity Framework и ASP.NET MVC 3. Первые главы вы можете найти по следующим ссылкам:

На прошлом уроке мы завершили работу над моделью данных School. В этом руководстве мы загрузим и отобразим необходимые данные, загруженные Entity Framework, в свойствах навигации.

На иллюстрации показаны результаты нашей работы.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC



Ленивая, нетерпеливая и явная загрузка необходимых данных

Существует несколько методов, которые EF использует для загрузки необходимых данных в свойства навигации сущности:
  • Ленивый загрузка .

    При первом доступе к объекту связанные данные не загружаются.

    Однако при первом доступе к свойству навигации связанные данные загружаются автоматически.

    В этом случае к базе данных делается множество запросов: один для сущности и один при каждой загрузке данных.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

  • Жаждущий загрузка .

    Данные загружаются при доступе к объекту.

    Обычно за этим следует один запрос на соединение, который возвращает все данные.

    Вы можете указать использование быстрой загрузки с помощью метода Include.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

  • Явный загрузка .

    Этот метод похож на отложенную загрузку, за исключением того, что вы сами указываете загрузку данных — это не происходит автоматически при доступе к свойству навигации.

    Данные загружаются вручную с помощью диспетчера состояния объекта сущности и вызова метода Collection.Load для коллекций и метода Reference.Load для свойств с одним значением.

    (в этом примере, если вы хотите загрузить свойство навигации «Администратор», замените Collection(x => x.Courses) на Reference(x => x.Administrator).

    )



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

В связи с тем, что данные загружаются не сразу, отложенная загрузка и явная загрузка имеют одно и то же название.

отложенный загрузка .

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

Например, представьте, что каждое отделение предлагает десять курсов.

Пример активной загрузки будет сопровождаться одним запросом на присоединение.

Далее будут приведены одиннадцать примеров отложенной и явной загрузки.

С другой стороны, если к свойствам навигации сущностей обращаются редко или используется небольшое количество сущностей, отложенная загрузка может быть более эффективной — нетерпеливая загрузка загрузит больше данных, чем необходимо.

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

Допустим, существует ситуация, когда отложенную загрузку можно отключить во время сериализации, когда вы уверены, что вам не нужны все свойства навигации.

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

Класс контекста базы данных по умолчанию использует отложенную загрузку.

Есть два способа отключить отложенную загрузку:

  • При объявлении свойств навигации опустите модификатор virtual.
  • Установите для LazyLoadingEnabled значение false для всех свойств навигации.

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

Например, код, который не использует нетерпеливую или явную загрузку, но использует большое количество сущностей и несколько свойств навигации в цикле, может быть очень неэффективным из-за большого количества вызовов базы данных, но подойдет, если используется отложенная загрузка.

Временное отключение отложенной загрузки — один из способов найти код, использующий отложенную загрузку.

В этом случае свойства навигации будут иметь значение NULL и возникнет ошибка.

Создание страницы Курсы Индекс Сущность Course имеет свойство навигации, содержащее сущность Department — сущность факультета, которому принадлежит этот курс.

Чтобы отобразить название факультета, вам необходимо получить доступ к свойству Name соответствующей сущности.

Создайте контроллер типа Course:

Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

В Контроллеры\Курсеконтроллер.

cs обратите внимание на метод Index:

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   

public ViewResult Index() { var courses = db.Courses.Include(c => c.Department); return View(courses.ToList()); }

Автоматическое формирование шаблонов определяет использование быстрой загрузки для свойства навигации Department с использованием метода Include. В Просмотры\курс\индекс.

cshtml замените код на:

@model IEnumerable<ContosoUniversity.Models.Course> @{ ViewBag.Title = "Курсы"; } <h2>Courses</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th></th> <th>Number</th> <th>Title</th> <th>Credits</th> <th>Department</th> </tr> @foreach (var item in Model) { <tr> <td> @Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) | @Html.ActionLink("Details", "Details", new { id=item.CourseID }) | @Html.ActionLink("Delete", "Delete", new { id=item.CourseID }) </td> <td> @Html.DisplayFor(modelItem => item.CourseID) </td> <td> @Html.DisplayFor(modelItem => item.Title) </td> <td> @Html.DisplayFor(modelItem => item.Credits) </td> <td> @Html.DisplayFor(modelItem => item.Department.Name) </td> </tr> } </table>

Внесены следующие изменения:

  • Название изменено на Курсы .

  • Линии выравниваются по левому краю.

  • Добавлен столбец под заголовком Число , отображающий значение свойства CourseID. (Первичные ключи обычно не включаются на страницу, поскольку они не имеют значения, но в этом случае значение имеет смысл и его необходимо показать.

  • Заголовок последнего столбца изменен на Отделение .

Обратите внимание, что в последнем столбце отображается значение свойства Name сущности Department из свойства навигации Department:

<td> @Html.DisplayFor(modelItem => item.Department.Name) </td>

Выберите «Курсы», чтобы просмотреть список названий кафедр.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

Создание Инструкторы Индекс Страница со списком курсов и слушателей этих курсов Вы создадите контроллер и представление для сущности «Инструктор» для отображения страницы «Инструктор инструкторов»:

Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

Загрузка и отображение данных происходит по следующему сценарию:

  • В списке факультетов отображаются соответствующие данные объекта OfficeAssignment. Сущности Instructor и OfficeAssignment связаны «один к одному» или «один к одному».

    Сущность OfficeAssignment использует быструю загрузку.

  • Когда пользователь выбирает преподавателя, отображаются связанные сущности курса.

    Сущности «Инструктор» и «Курс» имеют отношение «многие ко многим».

    Вы будете использовать быструю загрузку для сущностей курса и связанных с ними сущностей отдела.

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

    Однако в примере показано использование быстрой загрузки.

  • Когда пользователь выбирает курс, отображаются данные сущности Enrollments. Сущности «Курс» и «Зачисление» имеют отношение «один ко многим».

    Вы добавите явную загрузку в сущность Enrollment и связанные с ней сущности Student. (Когда включена отложенная загрузка, использовать явную загрузку не обязательно, но мы просто покажем, как работает явная загрузка.

    )

Создание модели представления для представления Инструктор Индекс На странице «Указатель инструкторов» отображаются три разные таблицы.

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

В папке Просмотр моделей создавать ИнструкторИндексДанные.

cs :

using System; using System.Collections.Generic; using ContosoUniversity.Models; namespace ContosoUniversity.ViewModels { public class InstructorIndexData { public IEnumerable<Instructor> Instructors { get; set; } public IEnumerable<Course> Courses { get; set; } public IEnumerable<Enrollment> Enrollments { get; set; } } }



Стили для выбранных столбцов

Для выбранных столбцов требуется отдельный цвет фона.

Для этого добавьте следующий код в Содержание \ Сайт .

CSS :

/* MISC ----------------------------------------------------------*/ .

selectedrow { background-color: #EEEEEE; }



Создание контроллера и представлений для инструктора

Создайте контроллер типа Instructor:

Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

В Контроллеры\InstructorController.cs добавьте использование для ViewModels: использование ContosoUniversity.ViewModels; Сгенерированный код в методе Index определяет использование быстрой загрузки только для свойства навигации OfficeAssignment:

public ViewResult Index() { var instructors = db.Instructors.Include(i => i.OfficeAssignment); return View(instructors.ToList()); }

Замените метод Index следующим кодом, который загружает дополнительные данные и помещает их в модель представления:

public ActionResult Index(Int32? id, Int32? courseID) { var viewModel = new InstructorIndexData(); viewModel.Instructors = db.Instructors .

Include(i => i.OfficeAssignment) .

Include(i => i.Courses.Select(c => c.Department)) .

OrderBy(i => i.LastName); if (id != null) { ViewBag.InstructorID = id.Value; viewModel.Courses = viewModel.Instructors.Where(i => i.InstructorID == id.Value).

Single().

Courses; } if (courseID != null) { ViewBag.CourseID = courseID.Value; viewModel.Enrollments = viewModel.Courses.Where(x => x.CourseID == courseID).

Single().

Enrollments; } return View(viewModel); }

Метод принимает необязательные строковые параметры: значения идентификатора выбранного преподавателя и курса, а затем передает необходимые данные во представление.

Идентификаторы берутся из ссылок Выбирать На странице.

Код начинается с создания экземпляра модели представления и передачи ему списка учителей:

var viewModel = new InstructorIndexData(); viewModel.Instructors = db.Instructors .

Include(i => i.OfficeAssignment); .

Include(i => i.Courses.Select(c => c.Department)) .

OrderBy(i => i.LastName);

Мы определяем нетерпеливую загрузку для навигационного свойства Instructor.OfficeAssignment и Instructor.Courses. Для связанных сущностей активная загрузка курса определяется для свойства навигации Course.Department с использованием метода Select в методе Include. Результаты сортируются по фамилии.

Если выбран учитель, то этот учитель извлекается из списка преподавателей в модели данных, после чего свойство «Курсы» инициализируется сущностями «Курс» из свойства навигации «Курсы», соответствующего преподавателю.



if (id != null) { ViewBag.InstructorID = id.Value; viewModel.Courses = viewModel.Instructors.Where(i => i.InstructorID == id.Value).

Single().

Courses; }

Метод Where возвращает коллекцию, но в этом случае условие, переданное методу, указывает на возврат только одной сущности Instructor. Метод Single преобразует коллекцию в одну сущность Instructor, что позволяет получить доступ к свойству Courses, соответствующему этой сущности.

Метод Single используется для коллекции, если известно, что коллекция будет состоять из одного элемента.

Этот метод генерирует исключения, если коллекция пуста или состоит из более чем одного элемента.

Однако в этом случае будет выдано исключение (из-за свойства Course с нулевой ссылкой).

При вызове Single вместо отдельного вызова Where вы можете передать само условие: .

Single(i => i.InstructorID == id.Value) Вместо: .

Where(I => i.InstructorID == id.Value).

Single() Далее, если курс выбран, то этот курс извлекается из списка курсов в модели.

Свойство модели Enrollments затем инициализируется с помощью объектов свойств навигации Enrollments.

if (courseID != null) { ViewBag.CourseID = courseID.Value; viewModel.Enrollments = viewModel.Courses.Where(x => x.CourseID == courseID).

Single().

Enrollments; }

И наконец, возвращаясь к модели: вернуть представление (viewModel); Редактирование представление Индекс инструктора В Просмотры\Инструктор\Index.cshtml замените код на:

@model ContosoUniversity.ViewModels.InstructorIndexData @{ ViewBag.Title = "Инструкторы"; } <h2>Instructors</h2> <p> @Html.ActionLink("Create New", "Create") </p> <table> <tr> <th></th> <th>Last Name</th> <th>First Name</th> <th>Hire Date</th> <th>Office</th> </tr> @foreach (var item in Model.Instructors) { string selectedRow = ""; if (item.InstructorID == ViewBag.InstructorID) { selectedRow = "selectedrow"; } <tr class="@selectedRow" valign="top"> <td> @Html.ActionLink("Select", "Index", new { id = item.InstructorID }) | @Html.ActionLink("Edit", "Edit", new { id = item.InstructorID }) | @Html.ActionLink("Details", "Details", new { id = item.InstructorID }) | @Html.ActionLink("Delete", "Delete", new { id = item.InstructorID }) </td> <td> @item.LastName </td> <td> @item.FirstMidName </td> <td> @String.Format("{0:d}", item.HireDate) </td> <td> @if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location } </td> </tr> } </table>

Изменения:

  • Название страницы изменено на Инструкторы .

  • Столбцы ссылок строк перемещены влево.

  • Удаленный столбец Полное имя .

  • Столбец добавлен Офис, отображение item.OfficeAssignment.Location, если item.OfficeAssignment не имеет значения null. (Поскольку существует связь «один к нулю» или «один», с этой сущностью может отсутствовать какие-либо сущности OfficeAssignment.)


<td> @if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location } </td>

  • Добавлен код, который динамически добавляет class="selectedrow" в контейнер tr выбранного учителя.

    Таким образом, мы устанавливаем цвет фона с помощью класса CSS. (атрибут valign пригодится в будущем, когда мы добавим в таблицу многострочный столбец)



string selectedRow = ""; if (item.InstructorID == ViewBag.InstructorID) { selectedRow = "selectedrow"; } <tr class="@selectedRow" valign="top">

  • Перед ссылками в каждой строке добавлен новый ActionLink. Выбирать , что позволяет передать идентификатор выбранного учителя методу Index.
Запустите проект, чтобы увидеть список преподавателей.

На странице отображается свойство Location, связанное с сущностями OfficeAssignment, и пустая ячейка, если связанные сущности OfficeAssignment отсутствуют.

Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

В Взгляды \ Инструкторы \ Индекс .

cshtml После контейнера таблицы добавьте код, отображающий список курсов для выбранного преподавателя.



@if (Model.Courses != null) { <h3>Courses Taught by Selected Instructor</h3> <table> <tr> <th></th> <th>ID</th> <th>Title</th> <th>Department</th> </tr> @foreach (var item in Model.Courses) { string selectedRow = ""; if (item.CourseID == ViewBag.CourseID) { selectedRow = "selectedrow"; } <tr class="@selectedRow"> <td> @Html.ActionLink("Select", "Index", new { courseID = item.CourseID }) </td> <td> @item.CourseID </td> <td> @item.Title </td> <td> @item.Department.Name </td> </tr> } </table> }

Код загружает свойство модели представления «Курсы» для отображения списка курсов и отображает ссылку «Выбрать», которая передает идентификатор выбранного курса в метод Index. Выберите преподавателя и вы увидите таблицу с курсами этого преподавателя и факультетами, на которых преподаются курсы.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

Примечание если выбранная строка не меняет цвет, обновите страницу, иногда это необходимо для загрузки файла .

css. После добавленного вами кода добавьте код, который отображает список студентов, зачисленных на выбранный курс.



@if (Model.Enrollments != null) { <h3> Students Enrolled in Selected Course</h3> <table> <tr> <th>Name</th> <th>Grade</th> </tr> @foreach (var item in Model.Enrollments) { <tr> <td> @item.Student.FullName </td> <td> @item.Grade </td> </tr> } </table> }

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

Выберите преподавателя и нажмите на курс, чтобы увидеть набор студентов и оценки.



Курс обучения.
</p><p>
 Загрузка данных из Entity Framework в приложение ASP.NET MVC

Добавление Явный Загрузка В ИнструкторКонтроллер .

CS и обратите внимание, как метод Index загружает список студентов выбранного курса:

if (courseID != null) { ViewBag.CourseID = courseID.Value; viewModel.Enrollments = viewModel.Courses.Where(x => x.CourseID == courseID).

Single().

Enrollments; }

При загрузке списка преподавателей вы определили нетерпеливую загрузку для свойства навигации «Курсы» и свойств отдела каждого курса, затем отправили коллекцию «Курсы» в модель представления и теперь загружаете свойство навигации «Зачисления» из одной из сущностей в этом списке.

коллекция.

Поскольку вы не определили немедленную загрузку для свойства навигации Course.Enrollments, данные этого свойства отображаются на странице в результате отложенной загрузки.

Если вы отключите отложенную загрузку, свойство Enrollments будет иметь значение null независимо от количества студентов на курсе.

В этом случае, чтобы инициализировать свойство Enrollments, необходимо определить для него нетерпеливую или явную загрузку.

Чтобы определить явную загрузку, замените код метода Index на:

public ActionResult Index(Int32? id, Int32? courseID) { var viewModel = new InstructorIndexData(); viewModel.Instructors = db.Instructors .

Include(i => i.OfficeAssignment) .

Include(i => i.Courses.Select(c => c.Department)) .

OrderBy(i => i.LastName); if (id != null) { ViewBag.InstructorID = id.Value; viewModel.Courses = viewModel.Instructors.Where(i => i.InstructorID == id.Value).

Single().

Courses; } if (courseID != null) { ViewBag.CourseID = courseID.Value; var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).

Single(); db.Entry(selectedCourse).

Collection(x => x.Enrollments).

Load(); foreach (Enrollment enrollment in selectedCourse.Enrollments) { db.Entry(enrollment).

Reference(x => x.Student).

Load(); } viewModel.Enrollments = viewModel.Courses.Where(x => x.CourseID == courseID).

Single().

Enrollments; } return View(viewModel); }

После загрузки выбранной сущности «Курс» новый код явно загружает свойства «Зачисления»: db.Entry(selectedCourse).

Collection(x => x.Enrollments).

Load(); Затем явно загружаются сущности Student: db.Entry(зачисление).

Reference(x => x.Student).

Load(); Обратите внимание, что вы используете метод Collection для инициализации свойства коллекции, но для свойства одного элемента вы используете метод Reference. Теперь вы можете открыть страницу Instructor Index — внешне ничего не изменилось, но изменился принцип загрузки данных.

Итак, вы использовали все три способа загрузки данных в свойства навигации.

На следующем уроке вы узнаете, как обновлять связанные данные.



Благодарности

Благодарим Александра Белоцерковского за помощь в переводе ( Ариман ).

Теги: #ASP.NET #asp.net mvc #entity framework

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.