Relace 1:1

Relace 1:1 se používají, když je jedna entita přidružená k jedné jiné entitě. Například Blog má jeden BlogHeadera který BlogHeader patří do jednoho Blog.

Tento dokument je strukturovaný kolem mnoha příkladů. Příklady začínají běžnými případy, které také představují koncepty. Pozdější příklady pokrývají méně běžné druhy konfigurace. Dobrým přístupem je porozumět několika prvním příkladům a konceptům a pak přejít k pozdějším příkladům na základě vašich konkrétních potřeb. Na základě tohoto přístupu začneme jednoduchými "povinnými" a "volitelnými" relacemi 1:1.

Tip

Kód pro všechny níže uvedené příklady najdete v OneToOne.cs.

Povinné 1:1

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

Relace 1:1 se skládá z:

Tip

Není vždy zřejmé, která strana relace 1:1 by měla být objektem zabezpečení a která strana by měla být závislá. Mezi důležité informace patří:

  • Pokud databázové tabulky pro oba typy již existují, musí se tabulka se sloupci cizího klíče namapovat na závislý typ.
  • Typ je obvykle závislý typ, pokud nemůže logicky existovat bez druhého typu. Například nemá smysl mít hlavičku pro blog, který neexistuje, takže BlogHeader je přirozeně závislý typ.
  • Pokud existuje vztah přirozeného nadřazeného/podřízeného objektu, je podřízený typ obvykle závislým typem.

Proto pro relaci v tomto příkladu:

  • Vlastnost BlogHeader.BlogId cizího klíče není nullable. Díky tomu je relace povinná, protože každá závislá (BlogHeader) musí souviset s určitým objektem zabezpečení (Blog), protože jeho vlastnost cizího klíče musí být nastavena na určitou hodnotu.
  • Obě entity mají navigace odkazující na související entitu na druhé straně relace.

Poznámka:

Požadovaná relace zajišťuje, že každá závislá entita musí být přidružená k určité hlavní entitě. Hlavní entita však může vždy existovat bez jakékoli závislé entity. To znamená, že povinný vztah neznamená, že vždy bude závislá entita. V modelu EF neexistuje žádný způsob a také standardní způsob v relační databázi, aby se zajistilo, že je objekt zabezpečení přidružený k závislému objektu. Pokud je to potřeba, musí se implementovat v aplikační (obchodní) logice. Další informace najdete v části Požadované navigace.

Tip

Relace se dvěma navigacemi – 1 ze závislých na objektu zabezpečení a inverzní z objektu zabezpečení k závislému – se označuje jako obousměrná relace.

Tento vztah je zjištěn konvencí. To znamená:

  • Blog je zjištěn jako objekt zabezpečení v relaci a BlogHeader je zjištěn jako závislý.
  • BlogHeader.BlogId je zjištěn jako cizí klíč závislého odkazujícího na Blog.Id primární klíč objektu zabezpečení. Relace se zjistí podle potřeby, protože BlogHeader.BlogId není možné použít hodnotu null.
  • Blog.BlogHeader je zjištěn jako referenční navigace.
  • BlogHeader.Blog je zjištěn jako referenční navigace.

Důležité

Při použití typů odkazů s možnou hodnotou null jazyka C# musí být navigace ze závislého objektu na objekt zabezpečení null, pokud je vlastnost cizího klíče nullable. Pokud je vlastnost cizího klíče nenulová, může být navigace nullable nebo ne. V tomto případě BlogHeader.BlogId je nenulovatelná a BlogHeader.Blog je také nenulová. Konstruktor = null!; se používá k označení tohoto jako záměrného pro kompilátor jazyka C#, protože EF obvykle nastaví Blog instanci a pro plně načtenou relaci nemůže mít hodnotu null. Další informace najdete v tématu Práce s odkazovými typy s možnou hodnotou Null.

V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

V příkladu výše spustí konfigurace relací typ hlavní entity (Blog). Stejně jako u všech relací je to přesně stejné jako začít se závislým typem entity (BlogHeader) místo toho. Příklad:

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

Žádná z těchto možností není lepší než druhá; Oba mají za následek naprosto stejnou konfiguraci.

Tip

Nikdy není nutné konfigurovat relaci dvakrát, jednou od objektu zabezpečení a pak znovu začít ze závislého objektu. Pokus o konfiguraci objektu zabezpečení a závislých polovin relace obecně nefunguje. Zvolte, jestli chcete nakonfigurovat každou relaci z jednoho konce nebo druhé, a pak konfigurační kód zapište pouze jednou.

Volitelné 1:1

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

To je stejné jako v předchozím příkladu, s tím rozdílem, že vlastnost cizího klíče a navigace na objekt zabezpečení jsou nyní null. Díky tomu je relace "volitelná", protože závislá (BlogHeader) nemůžesouviset s žádným objektem zabezpečení (Blog) nastavením jeho vlastnosti cizího klíče a navigace na null.

Důležité

Při použití typů odkazů s možnou hodnotou null jazyka C# musí být navigační vlastnost závislá na objektu zabezpečení null, pokud je vlastnost cizího klíče nullable. V tomto případě BlogHeader.BlogId je možné použít hodnotu null, takže BlogHeader.Blog musí být také s možnou hodnotou null. Další informace najdete v tématu Práce s odkazovými typy s možnou hodnotou Null.

Stejně jako předtím je tento vztah zjištěn konvencí. V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Požadovaná relace 1:1 s primárním klíčem k primárnímu klíči

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

Na rozdíl od relací 1:N může závislý konec relace 1:1 použít vlastnost nebo vlastnosti primárního klíče jako vlastnost nebo vlastnosti cizího klíče. Tomu se často říká vztah PK-to-PK. To je možné pouze v případě, že objekt zabezpečení a závislé typy mají stejné typy primárních klíčů a výsledná relace je vždy vyžadována, protože primární klíč závislého nesmí být nullable.

Všechny relace 1:1, kde cizí klíč není zjištěn konvencí, musí být nakonfigurována tak, aby indikovala instanční objekt a závislé konce relace. Obvykle se to provádí voláním HasForeignKey. Příklad:

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

Tip

HasPrincipalKey může se také použít pro tento účel, ale to je méně běžné.

Pokud není v volání HasForeignKeyzadána žádná vlastnost a primární klíč je vhodný, použije se jako cizí klíč. V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Vyžadováno 1:1 se stínovým cizím klíčem

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

V některých případech nemusí být v modelu požadována vlastnost cizího klíče, protože cizí klíče jsou podrobností o způsobu znázornění relace v databázi, která není nutná při použití relace čistě objektově orientovaným způsobem. Pokud se ale entity budou serializovat, například odeslat přes drát, pak hodnoty cizího klíče mohou být užitečným způsobem, jak zachovat informace relace beze změny, pokud entity nejsou ve formě objektu. Proto je pro tento účel často praktická udržovat vlastnosti cizího klíče v typu .NET. Vlastnosti cizího klíče můžou být soukromé, což je často dobrým kompromisem, aby se zabránilo zveřejnění cizího klíče a zároveň jeho hodnota mohla cestovat s entitou.

Následující příklad z předchozího příkladu odebere vlastnost cizího klíče ze závislého typu entity. Místo použití primárního klíče je však ef místo toho instruován k vytvoření stínové vlastnosti cizího klíče volané BlogId typu int.

Tady je důležité poznamenat, že se používají odkazové typy s možnou hodnotou null jazyka C#, takže k určení, zda je vlastnost cizího klíče volitelná nebo povinná, se používá možnost null navigace ze závislého objektu na objekt zabezpečení. Pokud se nepoužívají odkazové typy s možnou hodnotou null, vlastnost stínového cizího klíče bude ve výchozím nastavení nastavena jako volitelná. V tomto případě použijte IsRequired k vynucení, aby vlastnost stínového cizího klíče byla nenulová a aby byla relace povinná.

Tato relace znovu potřebuje určitou konfiguraci, která indikuje hlavní objekt a závislé konce:

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

V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Volitelný 1:1 se stínovým cizím klíčem

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

Stejně jako v předchozím příkladu byla vlastnost cizího klíče odebrána ze závislého typu entity. Na rozdíl od předchozího příkladu je však vlastnost cizího klíče vytvořena jako nullable, protože se používají odkazové typy C# s možnou hodnotou null a navigace na závislém typu entity je nullable. Díky tomu je relace volitelná.

Pokud se nepoužívají odkazové typy s možnou hodnotou null jazyka C#, vlastnost cizího klíče se ve výchozím nastavení vytvoří jako nullable. To znamená, že relace s automaticky vytvořenými stínovými vlastnostmi jsou ve výchozím nastavení volitelné.

Stejně jako předtím potřebuje tato relace určitou konfiguraci, která indikuje hlavní objekt a závislé konce:

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

V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

1:1 bez navigace na objekt zabezpeč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
}

V tomto příkladu byla vlastnost cizího klíče znovu zavedena, ale navigace na závislém objektu byla odebrána.

Tip

Relace pouze s jednou navigacemi ze závislého na objektu zabezpečení nebo jednoho z objektu zabezpečení do závislého objektu, ale ne s oběma relacemi se označuje jako jednosměrná relace.

Tato relace je zjištěna konvencí, protože je zjištěn cizí klíč, což značí závislé straně. V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Všimněte si, že volání WithOne nemá žádné argumenty. To je způsob, jak říct EF, že neexistuje žádná navigace od BlogHeader .Blog

Pokud konfigurace začíná z entity bez navigace, musí být typ entity na druhém konci relace explicitně zadán pomocí obecného HasOne<>() volání. Příklad:

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

1:1 bez navigace na objekt zabezpečení a se stínovým cizím klíčem

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

Tento příklad kombinuje dva z předchozích příkladů odebráním vlastnosti cizího klíče a navigace na závislém objektu.

Stejně jako předtím potřebuje tato relace určitou konfiguraci, která indikuje hlavní objekt a závislé konce:

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

Úplnou konfiguraci lze použít k explicitní konfiguraci názvu navigace a cizího klíče s odpovídajícím voláním IsRequired() nebo IsRequired(false) podle potřeby. Příklad:

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

1:1 bez navigace na závislé

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

Předchozí dva příklady obsahovaly navigaci z objektu zabezpečení na závislé, ale žádná navigace ze závislého objektu na objekt zabezpečení. Pro další pár příkladů se navigace na závislém objektu znovu zavádí, zatímco navigace na objektu zabezpečení se odebere.

Ef bude podle konvence s tím zacházet jako s relací 1:N. K tomu, aby byla 1:1, je potřeba provést několik minimálních konfigurací:

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

Znovu si všimněte, že WithOne() se volá bez argumentů, aby bylo možné označit, že v tomto směru neexistuje žádná navigace.

V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Pokud konfigurace začíná z entity bez navigace, musí být typ entity na druhém konci relace explicitně zadán pomocí obecného HasOne<>() volání. Příklad:

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

1:1 bez navigace

Někdy může být užitečné nakonfigurovat relaci bez navigace. Takový vztah může být manipulován pouze změnou hodnoty cizího klíče přímo.

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

Tato relace není zjištěna konvencí, protože neexistují žádné navigace označující, že tyto dva typy souvisejí. Lze ho nakonfigurovat explicitně v OnModelCreatingsouboru . Příklad:

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

Při této konfiguraci je vlastnost stále zjištěna jako cizí klíč podle konvence a relace je "požadována", BlogHeader.BlogId protože vlastnost cizího klíče není nullable. Vztah může být "volitelný" tím, že vlastnost cizího klíče je null.

Explicitnější konfigurace této relace je:

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

1:1 s alternativním klíčem

Ve všech dosud uvedených příkladech je vlastnost cizího klíče na závislém objektu omezena na vlastnost primárního klíče objektu zabezpečení. Cizí klíč lze místo toho omezit na jinou vlastnost, která se pak stane alternativním klíčem pro typ entity objektu zabezpečení. Příklad:

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

Tato relace není zjištěna konvencí, protože ef vždy vytvoří relaci s primárním klíčem. Lze ji nakonfigurovat explicitně pomocí OnModelCreating volání HasPrincipalKey. Příklad:

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

HasPrincipalKey lze kombinovat s dalšími voláními pro explicitní konfiguraci navigace, vlastností cizího klíče a povinné/volitelné povahy. Příklad:

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

1:1 se složeným cizím klíčem

V dosud uvedených příkladech se primární nebo alternativní vlastnost klíče objektu zabezpečení skládala z jedné vlastnosti. Primární nebo alternativní klíče lze také vytvořit ve formě více než jedné vlastnosti– označují se jako "složené klíče". Pokud má objekt zabezpečení relace složený klíč, musí být cizí klíč závislého klíče také složený klíč se stejným počtem vlastností. Příklad:

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

Tento vztah je zjištěn konvencí. Zjistí se však pouze v případě, že je složený klíč nakonfigurovaný explicitně, protože složené klíče se nezjistí automaticky. Příklad:

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

Důležité

Složená hodnota cizího klíče se považuje za null hodnotu, pokud některé z jejích hodnot vlastností mají hodnotu null. Složený cizí klíč s jednou vlastností null a jinou nenulovou hodnotou se nepovažuje za shodu primárního nebo alternativního klíče se stejnými hodnotami. Obě budou považovány za null.

Obojí HasForeignKey a HasPrincipalKey lze je použít k explicitní zadání klíčů s více vlastnostmi. Příklad:

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

Tip

Ve výše uvedeném kódu se volání HasKeyHasOne seskupila do vnořeného tvůrce. Vnoření tvůrci odeberou potřebu volat Entity<>()Entity<>() vícekrát pro stejný typ entity, ale jsou funkčně ekvivalentní volání vícekrát.

Požadované 1:1 bez kaskádového odstranění

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

Podle konvence jsou požadované relace nakonfigurované tak, aby kaskádové odstranění. Je to proto, že závislý objekt nemůže v databázi po odstranění objektu zabezpečení existovat. Databázi je možné nakonfigurovat tak, aby vygenerovala chybu, obvykle dochází k chybovému ukončení aplikace, místo automatického odstraňování závislých řádků, které už neexistují. To vyžaduje určitou konfiguraci:

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

Odkazování na 1:1

Ve všech předchozích příkladech se typ hlavní entity liší od závislého typu entity. To nemusí být případ. Například v následujících typech každá z nich Person volitelně souvisí s jinou 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
}

Tento vztah je zjištěn konvencí. V případech, kdy se navigace, cizí klíč nebo povinná/volitelná povaha relace nezjistí konvencí, je možné tyto věci nakonfigurovat explicitně. Příklad:

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

Poznámka:

U relací 1:1 odkazujících na sebe, protože typy objektů zabezpečení a závislých entit jsou stejné, určení typu, který obsahuje cizí klíč, neobjasňuje závislý konec. V tomto případě navigace zadaná v HasOne bodech závislých na objektu zabezpečení a navigace zadaná v WithOne bodech z objektu zabezpečení na závislé.