Introduzione alle relazioni
Questo documento fornisce una semplice introduzione alla rappresentazione delle relazioni nei modelli a oggetti e nei database relazionali, incluso il modo in cui EF Core esegue il mapping tra i due.
Relazioni nei modelli a oggetti
Una relazione definisce il modo in cui due entità sono correlate tra loro. Ad esempio, quando si modellano i post in un blog, ogni post è correlato al blog su cui viene pubblicato e il blog è correlato a tutti i post pubblicati in tale blog.
In un linguaggio orientato agli oggetti come C#, il blog e il post sono in genere rappresentati da due classi: Blog
e Post
. Ad esempio:
public class Blog
{
public string Name { get; set; }
public virtual Uri SiteUri { get; set; }
}
public class Post
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime PublishedOn { get; set; }
public bool Archived { get; set; }
}
Nelle classi precedenti non c'è nulla da indicare che Blog
e Post
sono correlati. È possibile aggiungerlo al modello a oggetti aggiungendo un riferimento da Post
a in Blog
cui viene pubblicato:
public class Post
{
public string Title { get; set; }
public string Content { get; set; }
public DateOnly PublishedOn { get; set; }
public bool Archived { get; set; }
public Blog Blog { get; set; }
}
Analogamente, la direzione opposta della stessa relazione può essere rappresentata come una raccolta di Post
oggetti in ogni Blog
oggetto :
public class Blog
{
public string Name { get; set; }
public virtual Uri SiteUri { get; set; }
public ICollection<Post> Posts { get; }
}
Questa connessione da Blog
a Post
e, inversamente, da Post
a Blog
è nota come "relazione" in EF Core.
Importante
Una singola relazione può in genere attraversare in entrambe le direzioni. In questo esempio, da Blog
a tramite la Blog.Posts
proprietà e da a Blog
tramite Post
la Post.Blog
proprietà .Post
Questa è una relazione, non due.
Suggerimento
In EF Core le Blog.Posts
proprietà e Post.Blog
sono denominate "navigations".
Relazioni nei database relazionali
I database relazionali rappresentano relazioni usando chiavi esterne. Ad esempio, usando SQL Server o AZURE SQL, è possibile usare le tabelle seguenti per rappresentare Post
le classi e Blog
:
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NULL,
[Content] nvarchar(max) NULL,
[PublishedOn] datetime2 NOT NULL,
[Archived] bit NOT 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);
CREATE TABLE [Blogs] (
[Id] int NOT NULL IDENTITY,
[Name] nvarchar(max) NULL,
[SiteUri] nvarchar(max) NULL,
CONSTRAINT [PK_Blogs] PRIMARY KEY ([Id]));
In questo modello relazionale, alle Posts
tabelle e Blogs
viene assegnata una colonna "chiave primaria". Il valore della chiave primaria identifica in modo univoco ogni post o blog. Inoltre, alla Posts
tabella viene assegnata una colonna "chiave esterna". La Blogs
colonna Id
chiave primaria fa riferimento alla BlogId
colonna chiave esterna della Posts
tabella. Questa colonna è "vincolata" in modo che qualsiasi valore nella BlogId
colonna di Posts
deve corrispondere a un valore nella Id
colonna di Blogs
. Questa corrispondenza determina il blog a cui è correlato ogni post. Ad esempio, se il BlogId
valore in una riga della Posts
tabella è 7, il post rappresentato da tale riga viene pubblicato nel blog con la chiave primaria 7.
Mapping delle relazioni in EF Core
Il mapping delle relazioni di EF Core riguarda il mapping della rappresentazione di chiave primaria/chiave esterna usata in un database relazionale ai riferimenti tra gli oggetti usati in un modello a oggetti.
Nel senso più semplice, questo implica:
- Aggiunta di una proprietà di chiave primaria a ogni tipo di entità.
- Aggiunta di una proprietà di chiave esterna a un tipo di entità.
- Associazione dei riferimenti tra tipi di entità con le chiavi primarie ed esterne per formare una singola configurazione di relazione.
Dopo aver apportato questo mapping, Entity Framework modifica i valori di chiave esterna in base alle esigenze quando i riferimenti tra gli oggetti cambiano e modificano i riferimenti tra gli oggetti in base alle esigenze quando i valori della chiave esterna cambiano.
Nota
Le chiavi primarie vengono usate per più di relazioni di mapping. Per altre informazioni, vedere Chiavi .
Ad esempio, i tipi di entità illustrati in precedenza possono essere aggiornati con le proprietà di chiave primaria ed esterna:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Uri SiteUri { get; set; }
public ICollection<Post> Posts { get; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PublishedOn { get; set; }
public bool Archived { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
Suggerimento
Le proprietà della chiave primaria e esterna non devono essere proprietà visibili pubblicamente del tipo di entità. Tuttavia, anche quando le proprietà sono nascoste, è importante riconoscere che esistono ancora nel modello di Entity Framework.
La proprietà chiave primaria di Blog
, Blog.Id
e la proprietà di chiave esterna di , Post.BlogId
, possono quindi essere associate ai riferimenti ("navigazione") tra i tipi di Post
entità (Blog.Posts
e Post.Blog
). Questa operazione viene eseguita automaticamente da Entity Framework quando si compila una relazione semplice come questa, ma può anche essere specificata in modo esplicito quando si esegue l'override del OnModelCreating
metodo di DbContext
. Ad esempio:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasMany(e => e.Posts)
.WithOne(e => e.Blog)
.HasForeignKey(e => e.BlogId)
.HasPrincipalKey(e => e.Id);
}
Ora tutte queste proprietà si comportano in modo coerente come rappresentazione di una singola relazione tra Blog
e Post
.
Scopri di più
EF supporta molti tipi diversi di relazioni, con molti modi diversi in cui queste relazioni possono essere rappresentate e configurate. Per esaminare esempi per diversi tipi di relazioni, vedere:
- Relazioni uno-a-molti, in cui una singola entità è associata a un numero qualsiasi di altre entità.
- Relazioni uno-a-uno, in cui una singola entità è associata a un'altra singola entità.
- Relazioni molti-a-molti, in cui un numero qualsiasi di entità è associato a un numero qualsiasi di altre entità.
Se non si ha esperienza con Entity Framework, provare gli esempi collegati nei punti elenco precedenti è un buon modo per ottenere un'impressione del funzionamento delle relazioni.
Per approfondire le proprietà dei tipi di entità coinvolti nel mapping delle relazioni, vedere:
- Chiavi esterne e principali nelle relazioni, che illustrano il mapping delle chiavi esterne al database.
- Spostamenti tra relazioni, che descrivono come gli spostamenti vengono sovrapposti a una chiave esterna per fornire una visualizzazione orientata agli oggetti della relazione.
I modelli ef vengono creati usando una combinazione di tre meccanismi: convenzioni, attributi di mapping e API del generatore di modelli. La maggior parte degli esempi mostra l'API di compilazione del modello. Per altre informazioni sulle altre opzioni, vedere:
- Convenzioni di relazione, che individuano i tipi di entità, le relative proprietà e le relazioni tra i tipi.
- Attributi di mapping delle relazioni, che possono essere usati in alternativa all'API di compilazione del modello per alcuni aspetti della configurazione delle relazioni.
Importante
L'API di compilazione del modello è l'origine finale della verità per il modello di Entity Framework, che ha sempre la precedenza sulla configurazione individuata per convenzione o specificata dagli attributi di mapping. È anche l'unico meccanismo con piena fedeltà per configurare ogni aspetto del modello di Entity Framework.
Altri argomenti correlati alle relazioni includono:
- Eliminazioni a catena, che descrivono come le entità correlate possono essere eliminate automaticamente quando
SaveChanges
oSaveChangesAsync
viene chiamato . - I tipi di entità di proprietà usano un tipo speciale di relazione "proprietario" che implica una connessione più forte tra i due tipi rispetto alle relazioni "normali" descritte qui. Molti dei concetti descritti qui per le relazioni normali vengono trasportati alle relazioni di proprietà. Tuttavia, le relazioni di proprietà hanno anche i propri comportamenti speciali.
Suggerimento
Fare riferimento al glossario dei termini di relazione in base alle esigenze durante la lettura della documentazione per comprendere la terminologia usata.
Uso delle relazioni
Le relazioni definite nel modello possono essere usate in vari modi. Ad esempio:
- Le relazioni possono essere usate per eseguire query sui dati correlati in uno dei tre modi seguenti:
- Le relazioni possono essere usate nel seeding dei dati tramite la corrispondenza dei valori PK con i valori FK.
- Le relazioni possono essere usate per tenere traccia dei grafici delle entità. Le relazioni vengono quindi usate dal rilevamento delle modifiche per:
- Rilevare le modifiche nelle relazioni ed eseguire la correzione
- Inviare aggiornamenti delle chiavi esterne al database con
SaveChanges
oSaveChangesAsync