Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
EF Core usa un modello di metadati per descrivere il mapping dei tipi di entità dell'applicazione al database sottostante. Questo modello viene creato usando un set di convenzioni , euristica che cercano modelli comuni. Il modello può quindi essere personalizzato usando attributi di mapping (noti anche come annotazioni di dati) e/o chiamate ai ModelBuilder metodi (noti anche come API Fluent) in OnModelCreating, entrambi i quali eseguiranno l'override della configurazione eseguita dalle convenzioni.
La maggior parte della configurazione può essere applicata a un modello destinato a qualsiasi archivio dati. I provider possono anche abilitare la configurazione specifica di un archivio dati specifico e possono anche ignorare la configurazione non supportata o non applicabile. Per la documentazione sulla configurazione specifica del provider, vedere la sezione Provider di database .
Suggerimento
È possibile visualizzare gli esempi di questo articolo in GitHub.
Usare l'API Fluent per configurare un modello
È possibile eseguire l'override del OnModelCreating
metodo nel contesto derivato e usare l'API Fluent per configurare il modello. Si tratta del metodo di configurazione più potente e consente di specificare la configurazione senza modificare le classi di entità. La configurazione dell'API Fluent ha la precedenza più alta e sostituirà le convenzioni e le annotazioni dei dati. La configurazione viene applicata nell'ordine in cui vengono chiamati i metodi e, in caso di conflitti, la chiamata più recente eseguirà l'override della configurazione specificata in precedenza.
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; }
}
Suggerimento
Per applicare la stessa configurazione a più oggetti nel modello, vedere configurazione in blocco.
Configurazione del raggruppamento
Per ridurre le dimensioni del OnModelCreating
metodo, è possibile estrarre tutte le configurazioni per un tipo di entità in una classe separata che implementa IEntityTypeConfiguration<TEntity>.
public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
public void Configure(EntityTypeBuilder<Blog> builder)
{
builder
.Property(b => b.Url)
.IsRequired();
}
}
Richiamare quindi il Configure
metodo da OnModelCreating
.
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
Applicazione di tutte le configurazioni in un assembly
È possibile applicare tutte le configurazioni specificate nei tipi che implementano IEntityTypeConfiguration
in un determinato assembly.
modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);
Annotazioni
L'ordine in cui verranno applicate le configurazioni non è definito, pertanto questo metodo deve essere usato solo quando l'ordine non è rilevante.
Uso di EntityTypeConfigurationAttribute
sui tipi di entità
Anziché chiamare Configure
in modo esplicito, un EntityTypeConfigurationAttribute può essere invece associato al tipo di entità così che EF Core possa trovare e usare la configurazione appropriata. Per esempio:
[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Isbn { get; set; }
}
Questo attributo significa che EF Core userà l'implementazione specificata IEntityTypeConfiguration
ogni volta che il Book
tipo di entità viene incluso in un modello. Il tipo di entità è incluso in un modello usando uno dei meccanismi normali. Ad esempio, creando una DbSet<TEntity> proprietà per il tipo di entità:
public class BooksContext : DbContext
{
public DbSet<Book> Books { get; set; }
//...
In alternativa, registrandolo in OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>();
}
Annotazioni
EntityTypeConfigurationAttribute
I tipi non verranno individuati automaticamente in un assembly. I tipi di entità devono essere aggiunti al modello prima che l'attributo venga individuato in tale tipo di entità.
Usare annotazioni di dati per configurare un modello
È anche possibile applicare determinati attributi (noti come Annotazioni dati) alle classi e alle proprietà. Le annotazioni dei dati sostituiranno le convenzioni, ma verranno sostituite dalla configurazione dell'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; }
}
Convenzioni predefinite
EF Core include molte convenzioni di compilazione di modelli abilitate per impostazione predefinita. È possibile trovarli tutti nell'elenco delle classi che implementano l'interfaccia IConvention . Tuttavia, tale elenco non include convenzioni introdotte da provider di database e plug-in di terze parti.
Le applicazioni possono rimuovere o sostituire una di queste convenzioni, nonché aggiungere nuove convenzioni personalizzate che applicano la configurazione per i modelli non riconosciuti da Entity Framework.
Suggerimento
Il codice riportato di seguito proviene da ModelBuildingConventionsSample.cs.
Rimozione di una convenzione esistente
A volte una delle convenzioni predefinite potrebbe non essere appropriata per l'applicazione, nel qual caso può essere rimossa.
Suggerimento
Se il modello non usa attributi di mapping (ovvero annotazioni di dati) per la configurazione, tutte le convenzioni con il nome che terminano AttributeConvention
possono essere rimosse in modo sicuro per velocizzare la compilazione del modello.
Esempio: Non creare indici per le colonne chiave esterna
In genere è opportuno creare indici per le colonne di chiave esterna (FK) e quindi esiste una convenzione predefinita per questo: ForeignKeyIndexConvention. Esaminando la vista di debug del modello per un Post
tipo di entità con relazioni con Blog
e Author
, è possibile vedere che vengono creati due indici: uno per BlogId
FK e l'altro per 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
Tuttavia, gli indici presentano un sovraccarico e potrebbe non essere sempre appropriato crearli per tutte le colonne FK. A tale scopo, è possibile rimuovere l'oggetto ForeignKeyIndexConvention
durante la compilazione del modello:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}
Esaminando ora la visualizzazione di debug del modello per Post
, vediamo che gli indici sui FK non sono stati creati.
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 si desidera, gli indici possono comunque essere creati in modo esplicito per le colonne di chiave esterna, utilizzando IndexAttribute o con la configurazione in OnModelCreating
.
Visualizzazione debug
È possibile accedere alla visualizzazione di debug del generatore di modelli nel debugger dell'IDE. Ad esempio, con Visual Studio:
È anche possibile accedervi direttamente dal codice, ad esempio per inviare la visualizzazione di debug alla console:
Console.WriteLine(context.Model.ToDebugString());
La visualizzazione di debug ha una forma breve e una forma lunga. Il modulo lungo include anche tutte le annotazioni, che possono essere utili se è necessario visualizzare metadati relazionali o specifici del provider. È possibile accedere alla visualizzazione lunga anche dal codice:
Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));