Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Обратная инженерия — это процесс формирования классов типов сущностей и класса DbContext на основе схемы базы данных. Этот процесс можно выполнить с помощью команды Scaffold-DbContext средств консоли диспетчера пакетов (PMC) EF Core или команды dotnet ef dbcontext scaffold средств интерфейса командной строки (CLI) .NET.
Note
Построение шаблонов для DbContext и типов сущностей, описанных здесь, отличается от генерации контроллеров в ASP.NET Core с помощью Visual Studio, которая здесь не описана.
Tip
Если вы используете Visual Studio, попробуйте расширение сообщества EF Core Power Tools . Эти средства предоставляют графическое средство, которое строится на основе средств командной строки EF Core и предлагает дополнительные параметры рабочего процесса и настройки.
Prerequisites
- Перед началом работы со scaffolding необходимо установить либо средства PMC, которые работают только в Visual Studio, либо средства .NET CLI, которые работают на любых платформах, поддерживаемых .NET.
- Установите пакет NuGet для
Microsoft.EntityFrameworkCore.Designв проект, в который вы создаёте шаблон. - Установите пакет NuGet для поставщика базы данных, предназначенного для схемы базы данных, из которой требуется создать шаблон.
Обязательные аргументы
Команды PMC и .NET CLI имеют два обязательных аргумента: строка подключения в базу данных и поставщик базы данных EF Core для использования.
строка подключения
Warning
В этой статье используется локальная база данных, которая не требует проверки подлинности пользователя. Рабочие приложения должны использовать самый безопасный поток проверки подлинности. Дополнительные сведения о проверке подлинности для развернутых тестовых и рабочих приложений см. в разделе "Безопасные потоки проверки подлинности".
Первый аргумент команды — строка подключения к базе данных. Инструменты используют эту строку подключения для чтения схемы базы данных.
Как строка подключения цитируется и экранируется зависит от оболочки, используемой для выполнения команды. Ознакомьтесь с документацией оболочки. Например, PowerShell требует экранирования $, но не \.
В следующем примере генерируются типы сущностей и DbContext из базы данных Chinook, расположенной на экземпляре SQL Server LocalDB данного компьютера, с использованием поставщика базы данных Microsoft.EntityFrameworkCore.SqlServer.
dotnet ef dbcontext scaffold "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook" Microsoft.EntityFrameworkCore.SqlServer
Tip
Конфигурацию можно использовать для хранения и получения строки подключения
Строки подключения в шаблонном коде
По умолчанию генератор каркасов будет включать строку подключения в сгенерированный код, но с предупреждением. Рассмотрим пример.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseSqlServer("Data Source=(LocalDb)\\MSSQLLocalDB;Database=AllTogetherNow");
Это делается так, чтобы созданный код не вызывал сбоя при первом использовании, что стало бы очень неприятным опытом обучения. Однако как говорится в предупреждении, строки подключения не должны существовать в рабочем коде. Сведения о различных способах управления строками подключения см. в разделе "Время существования DbContext, Конфигурация и Инициализация".
Tip
Параметр -NoOnConfiguring (Visual Studio PMC) или --no-onconfiguring (.NET CLI) можно передать, чтобы предотвратить создание метода OnConfiguring, содержащего строку подключения.
Имя поставщика
Второй аргумент — это имя поставщика. Имя поставщика обычно совпадает с именем пакета NuGet поставщика. Например, для SQL Server или SQL Azure используйте Microsoft.EntityFrameworkCore.SqlServer.
Параметры командной строки
Процесс формирования шаблонов можно контролировать различными параметрами командной строки.
Указание таблиц и представлений
По умолчанию все таблицы и представления в схеме базы данных автоматически преобразуются в типы сущностей. Вы можете ограничить, какие таблицы и представления являются шаблонами, указав схемы и таблицы.
Аргумент -Schemas (VISUAL Studio PMC) или --schema (.NET CLI) указывает схемы таблиц и представлений, для которых будут создаваться типы сущностей. Если этот аргумент опущен, все схемы включены. Если этот параметр используется, все таблицы и представления в схемах будут включены в модель, даже если они не включены с использованием -Tables или --table.
Аргумент -Tables (VISUAL Studio PMC) или --table (.NET CLI) указал таблицы и представления, для которых будут создаваться типы сущностей. Таблицы или представления в определенной схеме можно включить с помощью формата schema.table или schema.view. Если этот параметр не указан, будут включены все таблицы и представления. |
Например, чтобы сформировать каркас только для таблиц Artists и Albums.
dotnet ef dbcontext scaffold ... --table Artist --table Album
Чтобы сгенерировать все таблицы и представления из схем Customer и Contractor:
dotnet ef dbcontext scaffold ... --schema Customer --schema Contractor
Например, чтобы создать Purchases шаблон таблицы из Customer схемы, а также AccountsContracts таблицы из Contractor схемы:
dotnet ef dbcontext scaffold ... --table Customer.Purchases --table Contractor.Accounts --table Contractor.Contracts
Сохранение имен баз данных
Имена таблиц и столбцов по умолчанию исправляются, чтобы обеспечить более точное соответствие соглашениям об именовании .NET для типов и свойств. Указание -UseDatabaseNames (консоли пакетного менеджера Visual Studio) или --use-database-names (.NET CLI) отключает это поведение, максимально сохраняя исходные имена баз данных. Недопустимые идентификаторы .NET по-прежнему будут исправляться, а синтезированные имена, такие как свойства навигации, будут по-прежнему приводиться в соответствие с соглашениями об именовании .NET.
Например, рассмотрим следующие таблицы:
CREATE TABLE [BLOGS] (
[ID] int NOT NULL IDENTITY,
[Blog_Name] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Blogs] PRIMARY KEY ([ID]));
CREATE TABLE [posts] (
[id] int NOT NULL IDENTITY,
[postTitle] nvarchar(max) NOT NULL,
[post content] nvarchar(max) NOT NULL,
[1 PublishedON] datetime2 NOT NULL,
[2 DeletedON] datetime2 NULL,
[BlogID] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([id]),
CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogID]) REFERENCES [Blogs] ([ID]) ON DELETE CASCADE);
По умолчанию следующие типы сущностей будут сформированы из следующих таблиц:
public partial class Blog
{
public int Id { get; set; }
public string BlogName { get; set; } = null!;
public virtual ICollection<Post> Posts { get; set; } = new List<Post>();
}
public partial class Post
{
public int Id { get; set; }
public string PostTitle { get; set; } = null!;
public string PostContent { get; set; } = null!;
public DateTime _1PublishedOn { get; set; }
public DateTime? _2DeletedOn { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; } = null!;
public virtual ICollection<Tag> Tags { get; set; } = new List<Tag>();
}
Однако использование -UseDatabaseNames или --use-database-names приводит к следующим типам сущностей:
public partial class BLOG
{
public int ID { get; set; }
public string Blog_Name { get; set; } = null!;
public virtual ICollection<post> posts { get; set; } = new List<post>();
}
public partial class post
{
public int id { get; set; }
public string postTitle { get; set; } = null!;
public string post_content { get; set; } = null!;
public DateTime _1_PublishedON { get; set; }
public DateTime? _2_DeletedON { get; set; }
public int BlogID { get; set; }
public virtual BLOG Blog { get; set; } = null!;
}
Использование атрибутов сопоставления (также известные как заметки к данным)
Типы сущностей настраиваются с помощью ModelBuilder API по OnModelCreating умолчанию. Укажите -DataAnnotations (PMC) или --data-annotations (.NET CLI), чтобы вместо этого использовать атрибуты сопоставления , если это возможно.
Например, при использовании Fluent API строится следующая структура:
entity.Property(e => e.Title)
.IsRequired()
.HasMaxLength(160);
При использовании аннотаций данных подготавливается следующее:
[Required]
[StringLength(160)]
public string Title { get; set; }
Tip
Некоторые аспекты модели нельзя настроить с помощью атрибутов сопоставления. Скафолдер по-прежнему будет использовать API сборки модели для обработки этих случаев.
Имя DbContext
Имя класса, созданного с помощью шаблона DbContext, будет именем базы данных с суффиксом Context по умолчанию. Чтобы указать другой, используйте -Context в PMC и --context в .NET CLI.
Целевые каталоги и пространства имен
По умолчанию шаблоны классов сущностей и класса DbContext формируются в корневом каталоге проекта и используют пространство имен проекта.
Вы можете указать каталог, в котором формируются шаблоны классов, с помощью --output-dir. --context-dir позволяет сформировать шаблон класса DbContext в каталоге отдельно от классов типов сущностей:
dotnet ef dbcontext scaffold ... --context-dir Data --output-dir Models
По умолчанию пространство имен будет составлено из корневого пространства имен плюс имен подкаталогов внутри корневого каталога проекта. Однако можно переопределить пространство имен для всех выходных классов с помощью --namespace. Кроме того, вы можете переопределить пространство имен только для класса DbContext с помощью --context-namespace:
dotnet ef dbcontext scaffold ... --namespace Your.Namespace --context-namespace Your.DbContext.Namespace
Шаблонный код
Результатом формирования шаблонов из существующей базы данных является:
- Файл, содержащий класс, наследующийся от
DbContext - Файл для каждого типа сущности
Tip
Кроме того, начиная с EF 7, вы можете настраивать созданный код с помощью текстовых шаблонов T4. См. Настраиваемые шаблоны обратного проектирования для получения дополнительной информации.
Относительные типы C# допускающие значение NULL
Шаблон может создавать модели EF и типы сущностей, использующие ссылочные типы , допускающие значение NULL C# (NRTs). Использование NRT формируется автоматически при включении поддержки NRT в проекте C#, в котором выполняется формирование кода.
Например, в следующей таблице Tags содержатся как строковые столбцы, допускающие значения NULL, так и строковые столбцы, не допускающие значения NULL.
CREATE TABLE [Tags] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
[Description] nvarchar(max) NULL,
CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));
Это приводит к формированию соответствующих свойств строки, допускающих значения NULL и не допускающих значения NULL, в созданном классе:
public partial class Tag
{
public Tag()
{
Posts = new HashSet<Post>();
}
public int Id { get; set; }
public string Name { get; set; } = null!;
public string? Description { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
Аналогичным образом следующие таблицы Posts содержат необходимую связь с Blogs таблицей:
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NOT NULL,
[Contents] nvarchar(max) NOT NULL,
[PostedOn] datetime2 NOT NULL,
[UpdatedOn] datetime2 NULL,
[BlogId] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]));
Это приводит к формированию шаблона связи между блогами, не допускающими значения NULL (обязательно).
public partial class Blog
{
public Blog()
{
Posts = new HashSet<Post>();
}
public int Id { get; set; }
public string Name { get; set; } = null!;
public virtual ICollection<Post> Posts { get; set; }
}
И записи:
public partial class Post
{
public Post()
{
Tags = new HashSet<Tag>();
}
public int Id { get; set; }
public string Title { get; set; } = null!;
public string Contents { get; set; } = null!;
public DateTime PostedOn { get; set; }
public DateTime? UpdatedOn { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; } = null!;
public virtual ICollection<Tag> Tags { get; set; }
}
Связи "многие ко многим"
Процесс формирования шаблонов обнаруживает простые таблицы соединения и автоматически создает для них сопоставление "многие ко многим". Например, рассмотрим таблицы для Posts и Tags, а также таблицу объединения PostTag, соединяющую их:
CREATE TABLE [Tags] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NOT NULL,
[Description] nvarchar(max) NULL,
CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NOT NULL,
[Contents] nvarchar(max) NOT NULL,
[PostedOn] datetime2 NOT NULL,
[UpdatedOn] datetime2 NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]));
CREATE TABLE [PostTag] (
[PostsId] int NOT NULL,
[TagsId] int NOT NULL,
CONSTRAINT [PK_PostTag] PRIMARY KEY ([PostsId], [TagsId]),
CONSTRAINT [FK_PostTag_Posts_TagsId] FOREIGN KEY ([TagsId]) REFERENCES [Tags] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_PostTag_Tags_PostsId] FOREIGN KEY ([PostsId]) REFERENCES [Posts] ([Id]) ON DELETE CASCADE);
При применении scaffold-генерации это приводит к созданию класса для Post:
public partial class Post
{
public Post()
{
Tags = new HashSet<Tag>();
}
public int Id { get; set; }
public string Title { get; set; } = null!;
public string Contents { get; set; } = null!;
public DateTime PostedOn { get; set; }
public DateTime? UpdatedOn { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; } = null!;
public virtual ICollection<Tag> Tags { get; set; }
}
И класс для «Tag»:
public partial class Tag
{
public Tag()
{
Posts = new HashSet<Post>();
}
public int Id { get; set; }
public string Name { get; set; } = null!;
public string? Description { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
Но для таблицы PostTag не существует класса. Вместо этого конфигурация для связи "многие ко многим" формируется следующим образом:
entity.HasMany(d => d.Tags)
.WithMany(p => p.Posts)
.UsingEntity<Dictionary<string, object>>(
"PostTag",
l => l.HasOne<Tag>().WithMany().HasForeignKey("PostsId"),
r => r.HasOne<Post>().WithMany().HasForeignKey("TagsId"),
j =>
{
j.HasKey("PostsId", "TagsId");
j.ToTable("PostTag");
j.HasIndex(new[] { "TagsId" }, "IX_PostTag_TagsId");
});
Другие языки программирования
Пакеты EF Core, опубликованные корпорацией Майкрософт, создают код на C#. Однако базовая система шаблонов поддерживает модель подключаемого модуля для формирования шаблонов на других языках. Эта модель подключаемого модуля используется различными проектами, выполняемыми сообществом, например:
- EntityFrameworkCore.VisualBasic обеспечивает поддержку Visual Basic
- EFCore.FSharp обеспечивает поддержку F#
Настройка кода
Начиная с EF7, одним из лучших способов настройки созданного кода является настройка шаблонов T4, используемых для его создания.
Код также можно изменить после создания, но лучший способ сделать это зависит от того, планируется ли повторно запустить процесс формирования шаблонов при изменении модели базы данных.
Шаблон только один раз
При таком подходе каркасный код предоставляет отправную точку для кодового сопоставления в будущем. Любые изменения в созданном коде можно вносить по мере необходимости. Он становится нормальным кодом так же, как и любой другой код в проекте.
Синхронизация базы данных и модели EF можно выполнить одним из двух способов:
- Переключитесь на использование миграций базы данных EF Core и применяйте типы сущностей и конфигурацию модели EF в качестве источника истины, используя миграции чтобы сформировать схему.
- Вручную обновите типы сущностей и конфигурацию EF при изменении базы данных. Например, если новый столбец добавляется в таблицу, добавьте свойство для столбца в сопоставленный тип сущности и добавьте любую необходимую конфигурацию с помощью атрибутов сопоставления и (или) кода.
OnModelCreatingЭто относительно просто, с единственной реальной проблемой является процесс, чтобы убедиться, что изменения базы данных записываются или обнаруживаются каким-то образом, чтобы разработчики, ответственные за код, могли реагировать.
Повторяющееся формирование шаблонов
Альтернативный подход к шаблону один раз заключается в повторном создании шаблонов при каждом изменении базы данных. Это перезапишет любой ранее сгенерированный код, что означает, что любые изменения, внесенные в типы сущностей или конфигурацию EF в этом коде, будут потеряны.
[СОВЕТ] По умолчанию команды EF не перезаписывают существующий код для защиты от случайной потери кода. Аргумент
-Force(VISUAL Studio PMC) или--force(.NET CLI) можно использовать для принудительного перезаписи существующих файлов.
Так как шаблонный код будет перезаписан, рекомендуется не изменять его напрямую, а полагаться на частичные классы и методы, а также механизмы в EF Core, которые позволяют переопределить конфигурацию. Specifically:
- Класс
DbContextи классы сущностей генерируются как частичные. Это позволяет вводить дополнительные элементы и код в отдельный файл, который не переопределяется при запуске шаблонов. - Класс
DbContextсодержит частичный методOnModelCreatingPartial. Реализацию этого метода можно добавить в частичный класс для объектаDbContext. Затем он будет вызываться после вызоваOnModelCreating. - Конфигурация модели, созданная с помощью
ModelBuilderAPI, переопределяет любую конфигурацию, выполняемую соглашениями или атрибутами сопоставления, а также более раннюю конфигурацию, выполненную в построителе моделей. Это означает, что кодOnModelCreatingPartialможно использовать для переопределения конфигурации, созданной процессом формирования шаблонов, без необходимости удалить эту конфигурацию.
Наконец, помните, что начиная с EF7 шаблоны T4, используемые для создания кода, можно настроить. Это часто более эффективный подход, чем настраивание по умолчанию, а затем изменение с использованием частичных классов и/или методов.
Принцип работы
Реконструирование начинается с чтения схемы базы данных. При этом считываются сведения о таблицах, столбцах, ограничениях и индексах.
Затем на основе сведений о схеме создается модель EF Core. С помощью таблиц создаются типы сущностей, с помощью столбцов — свойства, а с помощью внешних ключей — связи.
Наконец, на основе модели создается код. Для соответствующих классов типов сущностей, текучего API и заметок к данным формируются шаблоны, чтобы можно было повторно создать ту же модель на основе приложения.
Limitations
- Не все сведения о модели можно представить с помощью схемы базы данных. Например, в схеме базы данных нет сведений об иерархиях наследования, принадлежащих типах и разделении таблиц. Из-за этого эти конструкции никогда не будут шаблонными.
- Кроме того, поставщик EF Core может не поддерживать некоторые типы столбцов. Эти столбцы не будут включены в модель.
- Маркеры параллелизма можно определить в модели EF Core, чтобы предотвратить одновременное обновление одной сущности двумя пользователями. Некоторые базы данных имеют специальный тип для представления этого типа столбца (например, rowversion в SQL Server), в этом случае мы можем перепроектировать эти сведения; однако другие маркеры параллелизма не будут шаблонными.