Partilhar via


Criando e configurando um modelo

O EF Core usa um modelo de metadados para descrever como os tipos de entidade do aplicativo são mapeados para o banco de dados subjacente. Este modelo é construído usando um conjunto de convenções - heurísticas que procuram padrões comuns. O modelo pode então ser personalizado usando atributos de mapeamento (também conhecidos como anotações de dados) e/ou chamadas para os ModelBuilder métodos (também conhecidos como API fluente) no OnModelCreating, que substituirão a configuração executada por convenções.

A maioria das configurações pode ser aplicada a um modelo direcionado a qualquer armazenamento de dados. Os provedores também podem habilitar a configuração específica para um armazenamento de dados específico e também podem ignorar a configuração que não é suportada ou não aplicável. Para obter documentação sobre a configuração específica do provedor, consulte a seção Provedores de banco de dados .

Sugestão

Você pode ver os exemplos deste artigo no GitHub.

Usar API fluente para configurar um modelo

Você pode substituir o método OnModelCreating no seu contexto derivado e usar a API fluente para configurar o seu modelo. Este é o método mais poderoso de configuração e permite que a configuração seja especificada sem modificar suas classes de entidade. A configuração de API fluente tem a maior precedência e substituirá convenções e anotações de dados. A configuração é aplicada na ordem em que os métodos são chamados e, se houver conflitos, a última chamada substituirá a configuração especificada anteriormente.

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; }
}

Sugestão

Para aplicar a mesma configuração a vários objetos no modelo, consulte Configuração em massa.

Configuração de agrupamento

Para reduzir o tamanho do método, toda a OnModelCreating configuração para um tipo de entidade pode ser extraída para uma classe separada implementando IEntityTypeConfiguration<TEntity>.

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

Em seguida, basta invocar o método Configure a partir de OnModelCreating.

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

Aplicando todas as configurações em uma montagem

É possível aplicar todas as configurações especificadas em tipos implementando IEntityTypeConfiguration em um determinado assembly.

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

Observação

A ordem em que as configurações serão aplicadas é indefinida, portanto, esse método só deve ser usado quando a ordem não importa.

Usando EntityTypeConfigurationAttribute em tipos de entidade

Em vez de chamar Configureexplicitamente , um EntityTypeConfigurationAttribute pode ser colocado no tipo de entidade de modo que o EF Core possa localizar e usar a configuração apropriada. Por exemplo:

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

Esse atributo significa que o EF Core usará a implementação especificada IEntityTypeConfiguration sempre que o tipo de Book entidade for incluído em um modelo. O tipo de entidade é incluído em um modelo usando um dos mecanismos normais. Por exemplo, criando uma propriedade para o tipo de entidade DbSet<TEntity>:

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

Ou registando-o em OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

Observação

EntityTypeConfigurationAttribute Os tipos não serão descobertos automaticamente num assembly. Os tipos de entidade devem ser adicionados ao modelo antes que o atributo seja descoberto nesse tipo de entidade.

Usar anotações de dados para configurar um modelo

Você também pode aplicar determinados atributos (conhecidos como Anotações de Dados) às suas classes e propriedades. As anotações de dados substituirão as convenções, mas serão substituídas pela configuração da API Fluent.

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; }
}

Convenções incorporadas

O EF Core inclui muitas convenções de construção de modelos habilitadas por padrão. Você pode encontrar todos eles na lista de classes que implementam a IConvention interface. No entanto, essa lista não inclui convenções introduzidas por provedores de banco de dados e plug-ins de terceiros.

Os aplicativos podem remover ou substituir qualquer uma dessas convenções, bem como adicionar novas convenções personalizadas que aplicam a configuração para padrões que não são reconhecidos pelo EF prontamente.

Sugestão

O código mostrado abaixo vem de ModelBuildingConventionsSample.cs.

Remoção de uma convenção existente

Às vezes, uma das convenções internas pode não ser apropriada para seu aplicativo, caso em que pode ser removida.

Sugestão

Se o seu modelo não usa atributos de mapeamento (também conhecidos como anotações de dados) para configuração, todas as convenções com o nome terminado em AttributeConvention podem ser removidas com segurança para acelerar a criação do modelo.

Exemplo: Não crie índices para colunas de chave estrangeira

Geralmente faz sentido criar índices para colunas de chave estrangeira (FK) e, portanto, há uma convenção interna para isso: ForeignKeyIndexConvention. Observando a visualização de depuração do modelo para um Post tipo de entidade com relações com Blog e Author, podemos ver que dois índices são criados: um para o BlogId FK e outro para o AuthorId FK.

  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

No entanto, os índices têm sobrecarga e nem sempre pode ser apropriado criá-los para todas as colunas FK. Para conseguir isso, o ForeignKeyIndexConvention pode ser removido ao construir o modelo:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}

Olhando para a visualização de depuração do modelo por Post enquanto, vemos que os índices em FKs não foram criados:

  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

Quando desejado, os índices ainda podem ser criados explicitamente para colunas de chave estrangeira, usando a IndexAttribute ou com a configuração em OnModelCreating.

Visualização de depuração

A vista de depuração da ferramenta de construção de modelos pode ser acessada no depurador de um IDE. Por exemplo, com o Visual Studio:

Aceder à vista de depuração do construtor de modelos a partir do depurador do Visual Studio

Ele também pode ser acessado diretamente do código, por exemplo, para enviar a visualização de depuração para o console:

Console.WriteLine(context.Model.ToDebugString());

A visualização de depuração tem um formulário curto e um formulário longo. O formulário longo também inclui todas as anotações, o que pode ser útil se você precisar visualizar metadados relacionais ou específicos do provedor. A visualização longa também pode ser acessada a partir do código:

Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));