Vytvoření a konfigurace modelu

EF Core používá model metadat k popisu mapování typů entit aplikace na podkladovou databázi. Tento model je sestaven pomocí sady konvencí – heuristiky, které hledají běžné vzory. Model je pak možné přizpůsobit pomocí atributů mapování (označovaných také jako datové poznámky) a/nebo volání ModelBuilder metod (označovaných také jako fluent API) v OnModelCreatingobou případech přepíše konfiguraci prováděnou konvencí.

Většinu konfigurace je možné použít u modelu, který cílí na jakékoli úložiště dat. Zprostředkovatelé mohou také povolit konfiguraci specifickou pro konkrétní úložiště dat a mohou také ignorovat konfiguraci, která není podporována nebo není použitelná. Dokumentaci ke konfiguraci specifické pro zprostředkovatele najdete v části Poskytovatelé databáze.

Tip

Ukázky tohoto článku můžete zobrazit na GitHubu.

Konfigurace modelu pomocí rozhraní Fluent API

Metodu OnModelCreating v odvozeném kontextu můžete přepsat a pomocí rozhraní API fluent nakonfigurovat model. Jedná se o nejúčinnější metodu konfigurace, která umožňuje určit konfiguraci beze změny tříd entit. Konfigurace rozhraní Fluent API má nejvyšší prioritu a přepíše konvence a datové poznámky. Konfigurace se použije v pořadí, v jakém se metody volají, a pokud dojde ke konfliktům, poslední volání přepíše dříve zadanou konfiguraci.

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

Tip

Pokud chcete stejnou konfiguraci použít u více objektů v modelu, podívejte se na hromadnou konfiguraci.

Konfigurace seskupení

Pokud chcete zmenšit velikost metody OnModelCreating, lze všechny konfigurace nějakého typu entity extrahovat do samostatné třídy implementující IEntityTypeConfiguration<TEntity>.

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

Pak stačí vyvolat metodu Configure z OnModelCreating.

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

Použití všech konfigurací v sestavení

V daném sestavení lze použít veškerou konfiguraci určenou v typech implementujících IEntityTypeConfiguration.

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

Poznámka

Pořadí, v jakém budou konfigurace použity, není definováno, proto by se tato metoda měla použít jen v případě, kdy nezáleží na pořadí.

Použití EntityTypeConfigurationAttribute u typů entit

Místo explicitního volání ConfigureEntityTypeConfigurationAttribute lze místo toho umístit na typ entity tak, aby EF Core mohl najít a použít odpovídající konfiguraci. Příklad:

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

Tento atribut znamená, že EF Core použije zadanou IEntityTypeConfiguration implementaci při každém Book zahrnutí typu entity do modelu. Typ entity je součástí modelu pomocí jednoho z normálních mechanismů. Například vytvořením DbSet<TEntity> vlastnosti pro typ entity:

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

    //...

Nebo ho zaregistrujete v OnModelCreating:

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

Poznámka

EntityTypeConfigurationAttribute typy nebudou automaticky zjištěny v sestavení. Typy entit musí být přidány do modelu před zjištěním atributu u tohoto typu entity.

Konfigurace modelu pomocí datových poznámek

U tříd a vlastností můžete také použít určité atributy (označované jako datové poznámky). Datové poznámky přepíší konvence, budou ale přepsány konfigurací rozhraní 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; }
}

Integrované konvence

EF Core obsahuje mnoho konvencí vytváření modelů, které jsou ve výchozím nastavení povolené. Všechny z nich najdete v seznamu tříd, které implementují IConvention rozhraní. Tento seznam ale neobsahuje konvence zavedené poskytovateli databází a moduly plug-in třetích stran.

Aplikace můžou některou z těchto konvencí odebrat nebo nahradit, a také přidat nové vlastní konvence, které použijí konfiguraci pro vzory , které EF nerozpozná.

Tip

Níže uvedený kód pochází z ModelBuildingConventionsSample.cs.

Odebrání existující konvence

Někdy některá z předdefinovaných konvencí nemusí být vhodná pro vaši aplikaci, v takovém případě je možné ji odebrat.

Tip

Pokud váš model pro konfiguraci nepoužívá atributy mapování (neboli datové poznámky), všechny konvence s názvem končícím názvem AttributeConvention je možné bezpečně odebrat, aby se urychlila sestavování modelu.

Příklad: Nevytvávejte indexy pro sloupce cizího klíče

Obvykle dává smysl vytvářet indexy pro sloupce cizího klíče (FK), a proto existuje předdefinovaná konvence pro toto: ForeignKeyIndexConvention. Při pohledu na zobrazení ladění modelu pro Post typ entity s relacemi Blog a Authorvidíme, že dva indexy jsou vytvořené – jeden pro FK a druhý pro BlogIdAuthorId 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

Indexy ale mají režijní náklady a nemusí být vždy vhodné je vytvořit pro všechny sloupce FK. Abyste toho dosáhli, ForeignKeyIndexConvention můžete ho při sestavování modelu odebrat:

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

Když se teď podíváme na zobrazení ladění modelu Post , vidíme, že se nevytvořily indexy ve 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

V případě potřeby lze indexy i nadále explicitně vytvářet pro sloupce cizího klíče, a to buď pomocí IndexAttribute konfigurace v OnModelCreating.

Zobrazení ladění

Zobrazení ladění tvůrce modelů je možné získat v ladicím programu integrovaného vývojového prostředí (IDE). Například se sadou Visual Studio:

Accessing the model builder debug view from the Visual Studio debugger

Můžete k němu přistupovat také přímo z kódu, například k odeslání zobrazení ladění do konzoly:

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

Zobrazení ladění má krátký formulář a dlouhý formulář. Dlouhý formulář obsahuje také všechny poznámky, které můžou být užitečné, pokud potřebujete zobrazit relační metadata nebo metadata specifická pro zprostředkovatele. K dlouhému zobrazení se dá přistupovat také z kódu:

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