Dela via


En-till-en-relationer

En-till-en-relationer används när en entitet är associerad med högst en annan entitet. Till exempel har en Blog en BlogHeader, och den BlogHeader tillhör endast en Blog.

Det här dokumentet är uppbyggt kring många exempel. Exemplen börjar med vanliga fall, som även introducerar begrepp. Senare exempel omfattar mindre vanliga typer av konfiguration. En bra metod här är att förstå de första exemplen och begreppen och sedan gå till de senare exemplen baserat på dina specifika behov. Baserat på den här metoden börjar vi med enkla "obligatoriska" och "valfria" en-till-en-relationer.

Tips/Råd

Koden för alla exempel nedan finns i OneToOne.cs.

Obligatoriskt en-till-en

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

En en-till-en-relation består av:

Tips/Råd

Det är inte alltid uppenbart vilken sida av ett en-till-en-förhållande som ska vara huvudparten och vilken sida som ska vara beroende. Några saker att tänka på är:

  • Om databastabellerna för de två typerna redan finns måste tabellen med sekundärnyckelkolumnerna mappas till den beroende typen.
  • En typ är vanligtvis den beroende typen om den inte kan finnas logiskt utan den andra typen. Till exempel är det inte meningsfullt att ha en rubrik för en blogg som inte finns, så BlogHeader är naturligtvis den beroende typen.
  • Om det finns en naturlig överordnad/underordnad relation är barnet vanligtvis den beroende typen.

Så för relationen i det här exemplet:

  • Egenskapen BlogHeader.BlogId främmande nyckel är inte nullbar. Detta gör relationen "obligatorisk" eftersom varje beroende (BlogHeader) måste vara relaterade till något huvud (Blog), eftersom dess främmande nyckelegenskap måste anges till något värde.
  • Båda entiteterna har navigering som pekar på den relaterade entiteten på andra sidan relationen.

Anmärkning

En nödvändig relation säkerställer att varje beroende entitet måste associeras med någon huvudentitet. En huvudentitet kan dock alltid finnas utan någon beroende entitet. Det innebär att en obligatorisk relation inte anger att det alltid kommer att finnas en beroende entitet. Det finns inget sätt i EF-modellen, och inte heller något standardmetod i en relationsdatabas, att säkerställa att en huvudentitet är associerad med en beroende entitet. Om detta behövs måste det implementeras i programlogik (affärslogik). Mer information finns i Obligatoriska navigeringar .

Tips/Råd

En relation med två navigeringar – en från beroende till huvudnamn och en inverterad från huvudnamn till beroende – kallas för en dubbelriktad relation.

Den här relationen identifieras av konventionen. Det är:

  • Blog identifieras som huvudnamn i relationen och BlogHeader identifieras som beroende.
  • BlogHeader.BlogId identifieras som en främmande nyckel för den beroende som refererar till huvudenhetens Blog.Id primära nyckel. Relationen upptäcks vid behov eftersom BlogHeader.BlogId inte kan vara null.
  • Blog.BlogHeader identifieras som en referensnavigering.
  • BlogHeader.Blog identifieras som en referensnavigering.

Viktigt!

När du använder nullbara referenstyper för C# måste navigeringen från den beroende objekttypen till huvudobjektet vara nullbar om egenskapen för den främmande nyckeln är nullbar. Om främmande nyckels egenskap inte är null, kan navigeringen vara null eller inte. I det här fallet är BlogHeader.BlogId icke-nullbar och BlogHeader.Blog är också icke-nullbar. Konstruktionen = null!; används för att markera detta som avsiktligt för C#-kompilatorn, eftersom EF vanligtvis anger instansen Blog och den inte kan vara null för en fullständigt inläst relation. Mer information finns i artikeln Att arbeta med nullbar-referenstyper.

För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

I exemplet ovan startar konfigurationen av relationerna den huvudsakliga entitetstypen (Blog). Precis som med alla relationer är det exakt detsamma som att börja med beroende entitetstyp (BlogHeader) i stället. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BlogHeader>()
        .HasOne(e => e.Blog)
        .WithOne(e => e.Header)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

Inget av dessa alternativ är bättre än det andra. båda resulterar i exakt samma konfiguration.

Tips/Råd

Det är aldrig nödvändigt att konfigurera en relation två gånger, en gång från huvudenheten och sedan igen från den beroende enheten. Dessutom fungerar det vanligtvis inte att försöka konfigurera huvud- och beroende halvor av en relation separat. Välj att konfigurera varje relation från ena änden eller den andra och skriv sedan konfigurationskoden bara en gång.

Valfritt en-till-en

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int? BlogId { get; set; } // Optional foreign key property
    public Blog? Blog { get; set; } // Optional reference navigation to principal
}

Detta är samma som i tidigare exempel, förutom att egenskapen främmande nyckel och navigeringen till huvudenheten nu är nullbara. Detta gör relationen "valfri" eftersom en beroende (BlogHeader) inte kan vara relaterad till någon huvudenhet (Blog) genom att ställa in dess utländska nyckelegenskap och navigering till null.

Viktigt!

När du använder nullbara referenstyper för C# måste navigeringsegenskapen från beroende till huvudobjektet vara nullbar om egenskapen för den främmande nyckeln är nullbar. I det här fallet BlogHeader.BlogId är nullbar, så BlogHeader.Blog måste också vara null. Mer information finns i artikeln Att arbeta med nullbar-referenstyper.

Precis som tidigare identifieras den här relationen av konventionen. För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired(false);
}

Krävs en-till-en-relation med primärnyckel till primärnyckel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Till skillnad från en-till-många-relationer kan den beroende änden av en en-till-en-relation använda dess primära nyckelegenskap eller egenskaper som egenskapen eller egenskaperna för sekundärnyckeln. Detta kallas ofta för en PK-to-PK relation. Detta är bara möjligt när huvudtyper och beroendetyp har samma primära nyckeltyper, och den resulterande relationen alltid är obligatorisk, eftersom den primära nyckeln för beroendetypen kan inte vara null.

Alla en-till-en-relationer där främmande nyckeln inte upptäcks genom konvention måste konfigureras för att indikera relationens huvudände och beroende ände. Detta görs vanligtvis med ett anrop till HasForeignKey. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>();
}

Tips/Råd

HasPrincipalKey kan också användas för detta ändamål, men det är mindre vanligt.

När ingen egenskap anges i anropet till HasForeignKey, och den primära nyckeln är lämplig, används den som sekundärnyckel. För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>(e => e.Id)
        .IsRequired();
}

Krävs en-mot-en med skugg-utländsk nyckel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

I vissa fall kanske du inte vill ha en sekundärnyckelegenskap i din modell, eftersom sekundärnycklar är en detalj i hur relationen representeras i databasen, vilket inte behövs när du använder relationen på ett rent objektorienterat sätt. Men om entiteter ska serialiseras, till exempel för att skicka över en tråd, kan sekundärnyckelvärdena vara ett användbart sätt att hålla relationsinformationen intakt när entiteterna inte är i ett objektformulär. Det är därför ofta pragmatiskt att behålla sekundärnyckelegenskaper i .NET-typen för detta ändamål. Främmande nyckelattribut kan vara privata, vilket ofta är en bra kompromiss för att undvika att exponera den främmande nyckeln samtidigt som dess värde kan vara kopplat till entiteten.

Efter föregående exempel tar detta exempel bort egenskapen för utländsk nyckel från den beroende entitetstypen. Men i stället för att använda den primära nyckeln instrueras EF i stället att skapa en skuggegenskap för sekundärnyckel som heter BlogId av typen int.

En viktig punkt att notera här är att C# nullable referenstyper används, vilket innebär att nullbarheten för navigeringen från beroende till huvudenhet används för att avgöra om främmandenyckelns egenskap är nullable och därför om relationen är frivillig eller obligatorisk. Om nullbara referenstyper inte används kommer egenskapen hos skugg-primärnyckeln att vara nullbar som standard, vilket gör att relationen blir valfri. I det här fallet kan du använda IsRequired för att tvinga egenskapen för sekundärnyckeln att inte vara null och göra relationen nödvändig.

Den här relationen behöver återigen konfigureras för att ange de primära och beroende ändarna.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId");
}

För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId")
        .IsRequired();
}

Valfritt en-till-en med skuggad främmande nyckel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public Blog? Blog { get; set; } // Optional reference navigation to principal
}

Precis som i föregående exempel har egenskapen extern nyckel tagits bort från den beroende entitetens typ. Men till skillnad från det tidigare exemplet skapas egenskapen för främmande nyckel som nullbar eftersom nullbara C#-referenstyper används och navigeringen på den beroende entitetstypen är nullbar. Detta gör relationen valfri.

När nullbara C#-referenstyper inte används kommer främmande nyckel-egenskapen som standard att skapas som nullbar. Det innebär att relationer med automatiskt skapade skuggegenskaper är valfria som standard.

Precis som tidigare behöver den här relationen viss konfiguration för att ange huvudnamnet och de beroende ändarna:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId");
}

För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>("BlogId")
        .IsRequired(false);
}

En till en utan navigering till huvudansvarig

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
}

I det här exemplet har den främmande nyckelegenskapen introducerats på nytt, men navigeringen på den beroende entiteten har tagits bort.

Tips/Råd

En relation med endast en navigering – en från beroende till huvudrelation eller en från huvudrelation till beroende, men inte båda – kallas för en enkelriktad relation.

Denna relation upptäcks av konventionen, eftersom den främmande nyckeln upptäcks, vilket indikerar den beroende sidan. För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne()
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

Observera att anropet till WithOne inte har några argument. Det här är sättet att berätta för EF att det inte finns någon navigering från BlogHeader till Blog.

Om konfigurationen startar från entiteten utan navigering måste typen av entitet i den andra änden av relationen uttryckligen anges med hjälp av det allmänna HasOne<>() anropet. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BlogHeader>()
        .HasOne<Blog>()
        .WithOne(e => e.Header)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

En-till-en-relation utan navigering till huvudobjektet och med skuggliknande främmande nyckel

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
}

Det här exemplet kombinerar två av de föregående exemplen genom att ta bort både egenskapen främmande nyckel och navigeringen på den beroende entiteten.

Precis som tidigare behöver den här relationen viss konfiguration för att ange huvudnamnet och de beroende ändarna:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne()
        .HasForeignKey<BlogHeader>("BlogId")
        .IsRequired();
}

En mer komplett konfiguration kan användas för att uttryckligen konfigurera navigerings- och utländska nyckelnamn, med ett lämpligt anrop till IsRequired() eller IsRequired(false) efter behov. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne()
        .HasForeignKey<BlogHeader>("BlogId")
        .IsRequired();
}

En-till-en utan navigering till beroende

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

De föregående två exemplen hade navigeringar från huvudkontot till beroenden, men ingen navigering från det beroende till huvudkontot. För de kommande exemplen introduceras navigeringen på den beroende entiteten på nytt, medan navigeringen på huvudobjektet tas bort istället.

Enligt konventionen behandlar EF detta som en en-till-många-relation. Det krävs en minimal konfiguration för att göra det till en-till-en:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BlogHeader>()
        .HasOne(e => e.Blog)
        .WithOne();
}

Observera igen att WithOne() anropas utan argument för att indikera att det inte finns någon navigering i den här riktningen.

För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BlogHeader>()
        .HasOne(e => e.Blog)
        .WithOne()
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

Om konfigurationen startar från entiteten utan navigering måste typen av entitet i den andra änden av relationen uttryckligen anges med hjälp av det allmänna HasOne<>() anropet. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne<BlogHeader>()
        .WithOne(e => e.Blog)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

En-till-en utan navigering

Ibland kan det vara användbart att konfigurera en relation utan navigering. En sådan relation kan bara manipuleras genom att ändra värdet för främmande nyckeln direkt.

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
}

Den här relationen identifieras inte av konventionen, eftersom det inte finns några navigeringer som anger att de två typerna är relaterade. Den kan konfigureras explicit i OnModelCreating. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne<BlogHeader>()
        .WithOne();
}

Med den här konfigurationen BlogHeader.BlogId identifieras egenskapen fortfarande som sekundärnyckel enligt konventionen, och relationen är "obligatorisk" eftersom egenskapen sekundärnyckel inte kan ogiltigförklaras. Relationen kan bli "valfri" genom att göra egenskapen för sekundärnyckeln nullbar.

En mer fullständig explicit konfiguration av den här relationen är::

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne<BlogHeader>()
        .WithOne()
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

En-till-en med alternativ nyckel

I alla exempel hittills är egenskapen främmande nyckel för den beroende begränsad till primärnyckelegenskapen för huvudobjektet. Sekundärnyckeln kan i stället begränsas till en annan egenskap, som sedan blir en alternativ nyckel för huvudentitetstypen. Till exempel:

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public int AlternateId { get; set; } // Alternate key as target of the BlogHeader.BlogId foreign key
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Den här relationen identifieras inte av konventionen, eftersom EF alltid, enligt konventionen, skapar en relation till den primära nyckeln. Det kan konfigureras explicit i OnModelCreating, genom ett anrop till HasPrincipalKey. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasPrincipalKey<Blog>(e => e.AlternateId);
}

HasPrincipalKey kan kombineras med andra anrop för att uttryckligen konfigurera navigationsmöjligheter, egenskaper för främmande nyckel och deras obligatoriska/valfria egenskap. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .HasPrincipalKey<Blog>(e => e.AlternateId)
        .HasForeignKey<BlogHeader>(e => e.BlogId)
        .IsRequired();
}

En-till-en med sammansatt utländsk nyckel

I alla exempel hittills bestod huvudobjektets primära eller alternativa nyckelegenskap av en enda egenskap. Primära eller alternativa nycklar kan också bildas i fler än en egenskap – dessa kallas "sammansatta nycklar". När huvudobjektet för en relation har en sammansatt nyckel måste den främmande nyckeln för den beroende enheten också vara en sammansatt nyckel med samma antal egenskaper. Till exempel:

// Principal (parent)
public class Blog
{
    public int Id1 { get; set; } // Composite key part 1
    public int Id2 { get; set; } // Composite key part 2
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId1 { get; set; } // Required foreign key property part 1
    public int BlogId2 { get; set; } // Required foreign key property part 2
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Den här relationen identifieras av konventionen. Det identifieras dock bara om den sammansatta nyckeln har konfigurerats explicit, eftersom sammansatta nycklar inte identifieras automatiskt. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasKey(e => new { e.Id1, e.Id2 });
}

Viktigt!

Ett sammansatt sekundärnyckelvärde anses vara null om något av dess egenskapsvärden är null. En sammansatt utländsk nyckel med en egenskap som är null och en annan som inte är null, betraktas inte som en matchning för en primär eller alternativ nyckel med samma värden. Båda kommer att betraktas som null.

Både HasForeignKey och HasPrincipalKey kan användas för att uttryckligen ange nycklar med flera egenskaper. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>(
        nestedBuilder =>
        {
            nestedBuilder.HasKey(e => new { e.Id1, e.Id2 });

            nestedBuilder.HasOne(e => e.Header)
                .WithOne(e => e.Blog)
                .HasPrincipalKey<Blog>(e => new { e.Id1, e.Id2 })
                .HasForeignKey<BlogHeader>(e => new { e.BlogId1, e.BlogId2 })
                .IsRequired();
        });
}

Tips/Råd

I koden ovan har anropen till HasKey och HasOne grupperats tillsammans i en kapslad byggare. Kapslade byggare tar bort behovet av att anropa Entity<>() flera gånger för samma entitetstyp, men är funktionellt likvärdiga med anrop Entity<>() flera gånger.

Krävs en-till-en utan kaskadborttagning

// Principal (parent)
public class Blog
{
    public int Id { get; set; }
    public BlogHeader? Header { get; set; } // Reference navigation to dependent
}

// Dependent (child)
public class BlogHeader
{
    public int Id { get; set; }
    public int BlogId { get; set; } // Required foreign key property
    public Blog Blog { get; set; } = null!; // Required reference navigation to principal
}

Enligt konventionen konfigureras nödvändiga relationer för kaskadborttagning. Det beror på att beroendet inte kan finnas i databasen när huvudkontot har tagits bort. Databasen kan konfigureras för att generera ett fel som vanligtvis får programmet att krascha, i stället för att automatiskt ta bort beroende rader som inte längre kan finnas. Detta kräver viss konfiguration:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasOne(e => e.Header)
        .WithOne(e => e.Blog)
        .OnDelete(DeleteBehavior.Restrict);
}

Självrefererande ett-till-ett

I alla tidigare exempel skiljer sig huvudentitetstypen från den beroende entitetstypen. Detta behöver inte vara fallet. I typerna nedan är var och en Person till exempel relaterad till en annan Person.

public class Person
{
    public int Id { get; set; }

    public int? HusbandId { get; set; } // Optional foreign key property
    public Person? Husband { get; set; } // Optional reference navigation to principal
    public Person? Wife { get; set; } // Reference navigation to dependent
}

Den här relationen identifieras av konventionen. För de fall där navigering, främmande nyckel eller nödvändig/valfri typ av relation inte identifieras av konventionen, kan dessa saker konfigureras uttryckligen. Till exempel:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .HasOne(e => e.Husband)
        .WithOne(e => e.Wife)
        .HasForeignKey<Person>(e => e.HusbandId)
        .IsRequired(false);
}

Anmärkning

För ett-till-ett-självrefererande relationer, eftersom de huvudsakliga och beroende entitetstyperna är desamma, klargör inte att ange vilken typ som innehåller den externa nyckeln den beroende änden. I det här fallet pekar navigeringen som anges i HasOne från beroende till huvudenhet, och navigeringen som anges i WithOne pekar från huvudenhet till beroende.