-
Модель данных. Создание базы данных. Заполнение базы данных. Метод
EnsureCreated
создает пустую базу данных, поэтому он размещается в методе инициализации БДDbInitializer.Initialize(context)
. -
EF Core CRUD
CREATE: обработка уязвимости Чрезмерная передача данных, с помощью методаTryUpdateModel
или модели представления (ViewModel) и методаentry.CurrentValues.SetValues(StudentVM);
EDIT: Если включать связанные данные не требуется, более эффективным будет методFindAsync
. Состояния сущностей.
DELETE: Обработка сбоя - операция удаления может завершиться сбоем из-за временных проблем с сетью. -
Сортировка, фильтрация, разбиение на страницы
Передача параметра сортировки в URL. Добавление фильтрации - производительность IQueryable и IEnumerable.
Разбиения по страницам. Создание класса PaginatedList.
Добавление группирования
Ранее в методе DbInitializer.Initialize мы сначала использовали метод EnsureCreated, который создает новую базу, каждый раз, когда меняется модель, затем мы добавляли данные в новую БД. Этот подход к обеспечению синхронизации базы данных с моделью данных хорошо работает до развертывания приложения в рабочей среде.
Приложение, выполняющееся в рабочей среде, обычно содержит данные. Приложение не может запускаться с тестовой базой данных каждый раз при внесении изменений (например, при добавлении столбца). Функция миграций EF Core решает эту проблему, позволяя EF Core обновить схему базы данных вместо создания базы данных.
⚠ Не вызывайте EnsureCreated() перед миграцией. EnsureCreated() обходит миграции, чтобы создать схему, что приводит к сбою мигграции.
Для этого в примере, первоначальная база удаляется, а метод EnsureCreated() комментируется в DbInitializer.Initialize
❶ После того, как вы определите начальную модель, можно переходить к созданию базы данных. Чтобы добавить первоначальную миграцию, используется команда PM Add-Migration InitialCreate
.
• После создания кода миграции проверьте, правильно ли он создан. Если потребуется, добавьте, удалите или измените любые операции для правильного применения изменений.
❷ Команда PM Update-Database
создаст новую пустую БД (это займет некоторе время). При этом в БД будет создана Таблица журнала миграции
Таблица __EFMigrationsHistory
используется для отслеживания миграций, которые были применены к базе данных, и она обязательна.
Кроме файлов миграции, будет создан файл Моментальный снимок модели данных Migrations/SchoolContextModelSnapshot.cs
. При добавлении миграции EF определяет, что именно изменилось, сравнивая текущую модель данных с файлом моментального снимка.
❸ Запустите приложение и убедитесь в том, что база данных заполняется. Это обеспечивает вызов метода DbInitializer.Initialize
при старте приложения, в файле Program.cs
Дополнительныe сведения:
📘 Управление схемами баз данных: Миграции
Использование атрибутов данных, требуются классы using System.ComponentModel.DataAnnotations
и
using System.ComponentModel.DataAnnotations.Schema
.
Атрибут Column
- сопоставляются с базой данных, а атриут Display
с отображением на странице. Запуск миграции после присвоения атрибутов.
Атрибут DatabaseGenerated - указывает, что первичный ключ предоставляется приложением, а не создается базой данных.
🟡 По соглашению EF Core разрешает каскадное удаление для внешних ключей, не допускающих значение null, и связей "многие ко многим". Это поведение по умолчанию может привести к циклическим правилам каскадного удаления. Такие правила вызывают исключение при добавлении миграции.
🔵 Составной ключ. Единственным способом указать составные первичные ключи для EF Core является текучий API, в методе SchoolContext.OnModelCreating:
modelBuilder.Entity<CourseAssignment>()
.HasKey(c => new { c.CourseID, c.InstructorID });
После изменения модели и добавления новых сущностей примените миграцию Add-Migration ComplexDataModel
. Если сразу выполнить команду Update-Database
то возникнет исключение:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Course_Department_DepartmentID". The conflict occurred in database "SchoolContext", table "dbo.Department", column 'DepartmentID'.
Это возникает из-за несогласованности текущих данных в БД с новой схемой данных. Нам надо изменить файл текущей миграции {метка_времени}_ComplexDataModel.cs
и добавить код, вставляющий временные данные, для согласования связей.
Устранение ограничений внешнего ключа
Теперь мы вновь делаем Update-Database
, запускается миграция, которая уже добавляет временные данные. Осталось заполнить данными вновь созданные сущности. Для данного примера пишется новая версия метода заполнителя, а база удаляется. Тогда при запуске приложения база будет вновь создана и заполнена новыми данными.
Безотложная загрузка. Безотложной является загрузка, когда запрос для одного типа сущности также загружает связанные сущности с помощью методов Include и ThenInclude.
Явная загрузка. При первом чтении сущности связанные данные не извлекаются. Нужно написать код, извлекающий связанные данные, когда они необходимы. Явная загрузка с отдельными запросами приводит к отправке нескольких запросов к базе данных. При явной загрузке код указывает, какие свойства навигации нужно загрузить. Для выполнения явной загрузки используется метод Load. Например:
Дополнительныe сведения:
📘 Загрузка связанных данных
⚠ При формировании шаблонов сущностей, обратите внимание на пространство имен для шаблонов. Должно быть включено пространство верхнего уровня ContosoUniversity.Pages.{имя_шаблона}
, например для Преподавателей должно быть namespace ContosoUniversity.Pages.Instructors
.
Это руководство описывает, как обрабатывать конфликты, когда несколько пользователей параллельно (одновременно) изменяют одну сущность.
- Пессимистичный параллелизм (блокировка) - EF Core не поддерживает,т.к. требует много ресурсов, используется оптимистическая блокировка. Варианты: отслживание изменений записи разными пользователями; победа клиента - сохранение последнего внесенного изменения; победа хранилища - если запись изменена другим пользователем (два пользователя одновременно редактируют запись), то будет сообщение об ошибке.
Данный метод гарантирует, что никакие изменения не перезаписываются без оповещения пользователя о случившемся - он и используется в примере. - Обнаружение конфликтов параллелизма - обработки исключений
DbConcurrencyException
- требует настройки БД и модели. В БД включаетя столбец отслеживанияrowversion
, он изменяется при каждом обновлении, и включается в запрос UPDATE или DELETE как часть предложения WHERE. - Добавление свойства отслеживания в БД
- Создание представлений и контроллера кафедр. Обновление страницы удаления. Обновление представлений Details и Create.
Дополнительныe ресурсы:
📘 Маркеры параллелизма в EF Core
📘 Обработка параллелизма в EF Core
📘 Отладка источника ASP.NET Core 2.x
📘 Реализация наследования, пример с MVC
📘 Сведения о сложных сценариях для ASP.NET MVC с EF Core
📘 Документации по платформе Entity Framework Core.
Практические консультации вы можете получить на наших веб курсах в Сочи, Адлер: