пятница, 9 ноября 2018 г.

EF.Core, Db First Подход. Scaffolding Lazy Loading

Ситуация. Делаю проект на .Net Core + Entity Framework Core
Использую DB First подход.

Хочу использовать Lazy Loading (По привычке работы с EF 6)

Проблема: стандартный скаффлодинг (через Scaffold-DbContext) не добавляет признака virtual у моделей-таблиц БД что необходимо для Lazy Loading-а.

При попытке запуска получаю ошибку

InvalidOperationException: Navigation property '(PropertyName)' on entity type '(EntityName)' is not virtual. UseLazyLoadingProxies requires all entity types to be public, unsealed, have virtual navigation properties, and have a public or protected constructor.

Как решил вопрос
перешел на скаффолдинг с использованием EF Core Power Tools

Установка:
Visual Studio -> меню Tools/Extensions And Updates

ищем EF Core Power Tools
устанавливаем

Далее скаффолдинг производим через конекстное меню проекта
пункт
EF Core Power Tools/Reverse Engineer

но тут есть нюанс, нужно в сгенерированный файл дбконтекста
добавить конструктор с параметром

public MyDbContext(DbContextOptions<MyDbContext> options)
            : base(options)
        {
        }


Далее, самый важный момент
собственно добавление поддержки Lazy Loading

при скаффолдинге через EF Core Power Tools нужно включить опцию
Customize code using Handlebars Templates



После этого в папке проекта появятся папкf CodeTemplates с подпапками


Чтобы добавить поддержку Lazy Loading в сгенерированный код, измените шаблон Properties.hbs в CSharpEntityType / Partials следующим образом:


{{spaces 8}}public virtual ICollection<{{nav-property-type}}> {{nav-property-name}} { get; set; }
{{spaces 8}}public virtual {{nav-property-type}} {{nav-property-name}} { get; set; }

УРА!
После следующей генерации таблиц навигационные свойства будут уже виртуальными

см. также
EF.Core, Db First Подход. Ошибка скаффолдинга (Scaffold-DbContext) Build Failure

что помогло
статья
https://stackoverflow.com/questions/50827976/scaffold-dbcontext-not-generating-virtual-navigation-properties-ef-core-2-1

и статья
https://github.com/ErikEJ/EFCorePowerTools/wiki/Reverse-Engineering

понедельник, 5 ноября 2018 г.

EF.Core, Db First Подход. Ошибка скаффолдинга (Scaffold-DbContext) Build Failure

Ситуация:

Работаю с .Net.Core проектом использую EF.Core с ви-ашкые подходом.
Сгенерировал контект и базу данных с помощью команды

Scaffold-DbContext "Server=(server);Database=(dbname);User ID=(user);Password=(password)" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

Первая генерация прошла хорошо.

Далее:
написал немного кода, добавил в солюшн AspNet.Core приложение.
провел изменение в базе данных и хочу перегенерировать модели БД.
Т.е. запустить Scaffold-DbContext во второй раз.

Чтобы не было пересечений - удаляю преварительно классы контекста БД и старые модели.

и, при запуске Scaffold-DbContext получаю ошибку

Build failed

Начал разбираться: нашел 2 варианта:

Вариант решения 1.
Обходной путь - подходит для небольших проектов


суть:
Выполняем 2 шага перед повторным скаффолдингом

Шаг 1. "Чистый" проект под модели (нужно сделеть 1 раз)
если в вашем солюшене несколько проектов, то оставьте модели базы данных в одном проекте и путсь в этом проекте не будет больше кода, который ссылается на эти модели.
Т.е. чтобы удаление моделей и контекста базы данных не приводило к ошибке компиляции проекта.

Шаг 2. Выгрузка других проектов перед скаффолдингом
Щелкаете правой кнопкой мыши на других проектах решения и выберите Unload Project

теперь можете стереть классы моделей и выполнить скаффолдинг

Только после скаффолдинга нужно будет вгрузить обатно выгруженные на шаге 2 проекты.

что помогло
статья
https://github.com/aspnet/EntityFrameworkCore/issues/9515

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

Вариант решения 2.
Используем EF Core Power Tools

Суть:
используем инструмент EF Core Core Power Tools в Visual Studio

Установка:
Visual Studio -> меню Tools/Extensions And Updates

ищем EF Core Power Tools
устанавливаем

Далее скаффолдинг производим через конекстное меню проекта
пункт
EF Core Power Tools/Reverse Engineer

но тут есть нюанс, нужно в сгенерированный файл дбконтекста
добавить конструктор с параметром

public MyDbContext(DbContextOptions<MyDbContext> options)
            : base(options)
        {
        }


Примечание
Дальше я столкнулся с проблемой Lazy Loading, её регение описал в отдельной статье
EF.Core, Db First Подход. Scaffolding Lazy Loading


что помогло
статья
https://stackoverflow.com/questions/50827976/scaffold-dbcontext-not-generating-virtual-navigation-properties-ef-core-2-1