Introduktion till relationer
Det här dokumentet ger en enkel introduktion till representationen av relationer i objektmodeller och relationsdatabaser, inklusive hur EF Core mappar mellan de två.
Relationer i objektmodeller
En relation definierar hur två entiteter relaterar till varandra. När du till exempel modellerar inlägg i en blogg är varje inlägg relaterat till den blogg som det publiceras på, och bloggen är relaterad till alla inlägg som publiceras på den bloggen.
I ett objektorienterat språk som C# representeras blogg och inlägg vanligtvis av två klasser: Blog
och Post
. Till exempel:
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; }
}
I klasserna ovan finns det inget som tyder på att Blog
och Post
är relaterade. Detta kan läggas till i objektmodellen genom att lägga till en referens från Post
till den Blog
som den publiceras på:
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; }
}
På samma sätt kan den motsatta riktningen för samma relation representeras som en samling Post
objekt på varje Blog
:
public class Blog
{
public string Name { get; set; }
public virtual Uri SiteUri { get; set; }
public ICollection<Post> Posts { get; }
}
Den här anslutningen från Blog
till Post
och omvänt från Post
tillbaka till Blog
kallas för en "relation" i EF Core.
Viktig
En enda förhållande kan vanligtvis traverseras i båda riktningarna. I det här exemplet är det från Blog
till Post
via egenskapen Blog.Posts
och från Post
tillbaka till Blog
via egenskapen Post.Blog
. Det här är en relation, inte två.
Tips
I EF Core kallas egenskaperna Blog.Posts
och Post.Blog
"navigering".
Relationer i relationsdatabaser
Relationsdatabaser representerar relationer med hjälp av främmande nycklar. Om du till exempel använder SQL Server eller Azure SQL kan följande tabeller användas för att representera våra Post
- och Blog
klasser:
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]));
I den här relationsmodellen får tabellerna Posts
och Blogs
vardera en "primärnyckelkolumn". Värdet för primärnyckeln identifierar unikt varje inlägg eller blogg. Dessutom får Posts
-tabellen en "främmande nyckel"-kolumn. Primärnyckelkolumnen Blogs
Id
refereras av den främmande nyckelkolumnen BlogId
i tabellen Posts
. Den här kolumnen är "begränsad" så att alla värden i kolumnen BlogId
i Posts
måste matcha ett värde i kolumnen Id
i Blogs
. Den här matchning avgör vilken blogg varje inlägg är relaterat till. Om till exempel BlogId
värdet på en rad i tabellen Posts
är 7 publiceras inlägget som representeras av den raden i bloggen med primärnyckeln 7.
Mappa relationer i EF Core
EF Core-relationsmappning handlar om att mappa den primära nyckel-/sekundärnyckelrepresentationen som används i en relationsdatabas till referenserna mellan objekt som används i en objektmodell.
I den mest grundläggande meningen innebär detta:
- Lägga till en primärnyckelegenskap till varje entitetstyp.
- Lägga till en utländsk nyckelegenskap till en entitetstyp.
- Associera referenserna mellan entitetstyper med de primära och externa nycklarna för att skapa en enda relationskonfiguration.
När den här mappningen har gjorts ändrar EF värdena för sekundärnyckeln efter behov när referenserna mellan objekt ändras och ändrar referenserna mellan objekt efter behov när sekundärnyckelvärdena ändras.
Notera
Primära nycklar används för mer än mappning av relationer. Mer information finns i Nycklar.
Till exempel kan de entitetstyper som visas ovan uppdateras med primär- och sekundärnyckelegenskaper:
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; }
}
Tips
Primär- och sekundärnyckelegenskaper behöver inte vara offentligt synliga egenskaper för entitetstypen. Men även när egenskaperna är dolda är det viktigt att känna igen att de fortfarande finns i EF-modellen.
Den primära nyckelegenskapen för Blog
, Blog.Id
och egenskapen främmande nyckel för Post
, Post.BlogId
kan kopplas ihop med referenserna ("navigeringar") mellan entitetstyperna (Blog.Posts
och Post.Blog
). Detta görs automatiskt av EF när du skapar en enkel relation som den här, men kan också anges uttryckligen när du åsidosättar OnModelCreating
-metoden för din DbContext
. Till exempel:
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);
}
Nu fungerar alla dessa egenskaper tillsammans som en representation av en enda relation mellan Blog
och Post
.
Ta reda på mer
EF stöder många olika typer av relationer, med många olika sätt att representera och konfigurera dessa relationer. För att snabbt komma igång med exempel för olika typer av relationer, se:
- En-till-många-relationer, där en enda entitet är associerad med valfritt antal andra entiteter.
- en-till-en-relationer, där en enda entitet är associerad med en annan enskild entitet.
- många-till-många-relationer, där valfritt antal entiteter är associerade med valfritt antal andra entiteter.
Om du är nybörjare på EF är det ett bra sätt att få en känsla för hur relationer fungerar genom att prova exemplen som är länkade i punktpunkterna ovan.
Mer information om egenskaperna för entitetstyper som ingår i relationsmappning finns i:
- Sekundär- och huvudnycklar i relationer, som beskriver hur sekundärnycklar mappas till databasen.
- Relationsnavigering, som beskriver hur navigeringar läggs över en främmande nyckel för att ge en objektorienterad vy över relationen.
EF-modeller skapas med hjälp av en kombination av tre mekanismer: konventioner, mappningsattribut och modellverktygets API. De flesta av exemplen visar modellskapande-API:et. Mer information om andra alternativ finns i:
- Relationskonventioner, som identifierar entitetstyper, deras egenskaper och relationerna mellan typerna.
- Relationsmappningsattribut, som kan användas som ett alternativ till modellskapande-API:et för vissa aspekter av relationskonfigurationen.
Viktig
Modellskapande-API:et är den slutliga sanningskällan för EF-modellen – den har alltid företräde framför konfigurationen som identifieras av konventionen eller anges av mappningsattribut. Det är också den enda mekanismen med fullständig exakthet för att konfigurera alla delar av EF-modellen.
Andra ämnen som rör relationer är:
-
Cascade tar bort, som beskriver hur relaterade entiteter kan tas bort automatiskt när
SaveChanges
ellerSaveChangesAsync
anropas. - Ägda entitetstyper använda en särskild typ av "ägande" relation som innebär en starkare anslutning mellan de två typerna än de "normala" relationer som beskrivs här. Många av de begrepp som beskrivs här för normala relationer överförs till ägda relationer. Men ägda relationer har också sina egna speciella beteenden.
Tips
Se ordlista över relationstermer efter behov när du läser dokumentationen för att förstå den terminologi som används.
Använda relationer
Relationer som definieras i modellen kan användas på olika sätt. Till exempel:
- Relationer kan användas för att hämta relaterad data på något av tre sätt:
- Relationer kan användas i datasåddning genom matchning av PK-värden till FK-värden.
- Relationer kan användas för att följa entitetsdiagram. Relationer används sedan av ändringsspåraren för att:
- Identifiera ändringar i relationer och utföra korrigeringar
-
Överför referensnyckeluppdateringar till databasen med
SaveChanges
ellerSaveChangesAsync