Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
EF Core использует модель метаданных для описания того, как типы сущностей приложения сопоставляются с базовой базой данных. Эта модель построена с помощью набора соглашений — эвристики, которые ищут общие шаблоны. Затем модель можно настроить с помощью атрибутов сопоставления (также известных как заметки данных) и (или) вызовов ModelBuilder методов (также известных как простой API) в OnModelCreating, оба из которых переопределяют конфигурацию, выполняемую соглашениями.
Большинство конфигураций можно применить к модели, предназначенной для любого хранилища данных. Поставщики также могут включить конфигурацию, которая относится к конкретному хранилищу данных, и они также могут игнорировать конфигурацию, которая не поддерживается или не применяется. Документация по конфигурации для конкретного поставщика см. в разделе "Поставщики баз данных ".
Использование fluent API для настройки модели
Вы можете переопределить метод OnModelCreating
в производном контексте и использовать Fluent API для настройки модели. Это самый мощный метод конфигурации и позволяет задавать конфигурацию без изменения классов сущностей. Конфигурация API Fluent имеет наивысший приоритет и переопределяет соглашения и атрибуты данных. Конфигурация применяется в том порядке, в каком порядке вызываются методы, и если возникают конфликты, последний вызов переопределит ранее указанную конфигурацию.
using Microsoft.EntityFrameworkCore;
namespace EFModeling.EntityProperties.FluentAPI.Required;
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
#region Required
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.IsRequired();
}
#endregion
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
Подсказка
Чтобы применить одну и ту же конфигурацию к нескольким объектам в модели, просмотрите массовую конфигурацию.
Настройка группировки
Чтобы уменьшить размер OnModelCreating
метода, можно извлечь всю конфигурацию для типа сущности в отдельный класс, реализующий IEntityTypeConfiguration<TEntity>.
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder
.Property(b => b.Url)
.IsRequired();
}
}
Затем просто вызовите Configure
метод из OnModelCreating
.
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
Применение всех конфигураций в сборке
Можно применить всю конфигурацию, указанную в типах, реализующихся IEntityTypeConfiguration
в данной сборке.
modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);
Замечание
Порядок применения конфигураций не определен, поэтому этот метод следует использовать только в том случае, если порядок не имеет значения.
Использование EntityTypeConfigurationAttribute
типов сущностей
Вместо явного вызова Configure
, EntityTypeConfigurationAttribute можно поместить на тип сущности, чтобы EF Core мог найти и использовать соответствующую конфигурацию. Рассмотрим пример.
[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Isbn { get; set; }
}
Этот атрибут означает, что EF Core будет использовать указанную IEntityTypeConfiguration
реализацию всякий раз, когда Book
тип сущности включен в модель. Тип сущности включен в модель с помощью одного из обычных механизмов. Например, создав DbSet<TEntity> свойство для типа сущности:
public class BooksContext : DbContext
{
public DbSet<Book> Books { get; set; }
//...
Или зарегистрируя его в OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>();
}
Замечание
EntityTypeConfigurationAttribute
типы не будут автоматически обнаружены в сборке. Типы сущностей необходимо добавить в модель, прежде чем атрибут будет обнаружен в этом типе сущности.
Использование заметок данных для настройки модели
К классам и свойствам можно также применять определенные атрибуты (известные как заметки данных). Аннотации данных переопределяют соглашения, но будут переопределены конфигурацией Fluent API.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace EFModeling.EntityProperties.DataAnnotations.Annotations;
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
[Table("Blogs")]
public class Blog
{
public int BlogId { get; set; }
[Required]
public string Url { get; set; }
}
Встроенные соглашения
EF Core включает множество соглашений о сборке моделей, которые включены по умолчанию. Все из них можно найти в списке классов, реализующих IConvention интерфейс. Однако этот список не включает соглашения, представленные сторонними поставщиками баз данных и подключаемыми модулями.
Приложения могут удалять или заменять любые из этих соглашений, а также добавлять новые пользовательские соглашения, которые применяют конфигурацию для паттернов, которые не распознаются EF из коробки.
Подсказка
Приведенный ниже код поступает из ModelBuildingConventionsSample.cs.
Удаление существующего соглашения
Иногда одно из встроенных соглашений может не подходить для приложения, в этом случае его можно удалить.
Подсказка
Если в вашей модели не используются атрибуты разметки (также известные как аннотации данных) для настройки, то все соглашения, имеющие в конце название AttributeConvention
, можно безопасно удалить, чтобы ускорить построение модели.
Пример. Не создавайте индексы для столбцов внешнего ключа
Обычно имеет смысл создавать индексы для столбцов внешнего ключа (FK), и поэтому для этого существует встроенное соглашение: ForeignKeyIndexConvention. Просматривая представление отладки модели для типа сущности Post
, у которой есть связи с Blog
и Author
, можно увидеть, что создаются два индекса — один для FK BlogId
, а другой — для FK AuthorId
.
EntityType: Post
Properties:
Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
AuthorId (no field, int?) Shadow FK Index
BlogId (no field, int) Shadow Required FK Index
Navigations:
Author (Author) ToPrincipal Author Inverse: Posts
Blog (Blog) ToPrincipal Blog Inverse: Posts
Keys:
Id PK
Foreign keys:
Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
Indexes:
AuthorId
BlogId
Однако индексы имеют издержки, и они не всегда подходят для создания всех столбцов FK. Для этого ForeignKeyIndexConvention
можно удалить при создании модели:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}
Глядя на представление отладки модели Post
сейчас, мы видим, что индексы на FK не созданы:
EntityType: Post
Properties:
Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
AuthorId (no field, int?) Shadow FK
BlogId (no field, int) Shadow Required FK
Navigations:
Author (Author) ToPrincipal Author Inverse: Posts
Blog (Blog) ToPrincipal Blog Inverse: Posts
Keys:
Id PK
Foreign keys:
Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
Если это необходимо, индексы по-прежнему могут быть явно созданы для внешних ключевых столбцов, либо с использованием IndexAttribute, либо с конфигурацией в OnModelCreating
.
Режим отладки
Режим отладки построителя моделей доступен в отладчике вашей интегрированной среды разработки. Например, с Visual Studio:
Доступ к нему также можно получить непосредственно из кода, например для отправки представления отладки в консоль:
Console.WriteLine(context.Model.ToDebugString());
Представление отладки имеет короткую форму и длинную форму. Длинная форма также содержит все заметки, которые могут быть полезны, если необходимо просмотреть реляционные или метаданные конкретного поставщика. Кроме того, можно получить доступ к длинному представлению из кода:
Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));