Aracılığıyla paylaş


Bire bir ilişkiler

Bire bir ilişkiler, bir varlık en fazla bir diğer varlıkla ilişkilendirildiğinde kullanılır. Örneğin, bir Blog vardır BlogHeaderve tek BlogHeaderBlogbir öğesine aittir.

Bu belge birçok örnek etrafında yapılandırılmıştır. Örnekler, kavramların da tanıtıldığı yaygın durumlarla başlar. Sonraki örnekler daha az yaygın yapılandırma türlerini kapsar. Burada iyi bir yaklaşım, ilk birkaç örneği ve kavramı anlamak ve ardından özel gereksinimlerinize göre sonraki örneklere gitmektir. Bu yaklaşıma dayanarak, basit "gerekli" ve "isteğe bağlı" bire bir ilişkilerle başlayacağız.

İpucu

Aşağıdaki tüm örneklerin kodu OneToOne.cs bulunabilir.

Gerekli bire bir

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

Bire bir ilişki şu kaynaklardan oluşur:

  • Asıl varlıkta bir veya daha fazla birincil veya alternatif anahtar özelliği. Örneğin, Blog.Id.
  • Bağımlı varlıkta bir veya daha fazla yabancı anahtar özelliği. Örneğin, BlogHeader.BlogId.
  • İsteğe bağlı olarak, bağımlı varlığa başvuran asıl varlıkta bir başvuru gezintisi . Örneğin, Blog.Header.
  • İsteğe bağlı olarak, asıl varlığa başvuran bağımlı varlıkta bir başvuru gezintisi . Örneğin, BlogHeader.Blog.

İpucu

Bire bir ilişkinin hangi tarafının sorumlu, hangi tarafının bağımlı olması gerektiği her zaman açık değildir. Dikkat edilmesi gereken bazı noktalar şunlardır:

  • İki türün veritabanı tabloları zaten varsa, yabancı anahtar sütunlarının bulunduğu tablo bağımlı türe eşlenmelidir.
  • Tür, diğer tür olmadan mantıksal olarak mevcut değilse genellikle bağımlı türdür. Örneğin, mevcut olmayan bir blog için üst bilgi sahibi olmak mantıklı değildir, bu nedenle BlogHeader doğal olarak bağımlı türdür.
  • Doğal bir üst/alt ilişki varsa, alt öğe genellikle bağımlı türdür.

Bu örnekteki ilişki için:

  • Yabancı anahtar özelliği BlogHeader.BlogId null atanamaz. Bu, yabancı anahtar özelliğinin bir değere ayarlanması gerektiğinden, her bağımlı () öğesinin bir sorumluyla (BlogHeaderBlog ) ilişkili olması gerektiğinden ilişkiyi "gerekli" yapar.
  • her iki varlığın da ilişkinin diğer tarafındaki ilgili varlığa işaret eden gezintileri vardır.

Not

Gerekli bir ilişki, her bağımlı varlığın bir asıl varlıkla ilişkilendirilmesini sağlar. Ancak, bir asıl varlık her zaman bağımlı varlık olmadan var olabilir. Başka bir ifadeyle, gerekli bir ilişki her zaman bağımlı bir varlık olacağını göstermez. EF modelinde hiçbir yol yoktur ve ayrıca bir sorumlunun bağımlı ile ilişkilendirildiğinden emin olmak için ilişkisel veritabanında standart bir yol yoktur. Bu gerekiyorsa, uygulama (iş) mantığında uygulanmalıdır. Daha fazla bilgi için bkz . Gerekli gezintiler .

İpucu

Biri bağımlıdan sorumluya, diğeri sorumludan bağımlıya olmak üzere iki gezinti içeren bir ilişki çift yönlü ilişki olarak bilinir.

Bu ilişki kural tarafından bulunur. Bunun anlamı:

  • Blog ilişkide sorumlu olarak bulunur ve BlogHeader bağımlı olarak bulunur.
  • BlogHeader.BlogId , sorumlunun birincil anahtarına başvuran bağımlının Blog.Id yabancı anahtarı olarak bulunur. İlişki, null atanamaz olduğundan BlogHeader.BlogId gerektiği gibi bulunur.
  • Blog.BlogHeader bir başvuru gezintisi olarak bulunur.
  • BlogHeader.Blog bir başvuru gezintisi olarak bulunur.

Önemli

C# null atanabilir başvuru türleri kullanılırken, yabancı anahtar özelliği null atanabilirse, bağımlı olandan sorumluya gezinti null atanabilir olmalıdır. Yabancı anahtar özelliği null atanamazsa, gezinti null atanabilir veya olamaz. Bu durumda, BlogHeader.BlogId null atanamaz ve BlogHeader.Blog aynı zamanda null atanamaz. Yapısı = null!; , bunu C# derleyicisi için kasıtlı olarak işaretlemek için kullanılır, çünkü EF genellikle örneği ayarlar Blog ve tam yüklü bir ilişki için null olamaz. Daha fazla bilgi için bkz . Null Atanabilir Başvuru Türleriyle Çalışma.

Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Yukarıdaki örnekte, ilişkilerin yapılandırması asıl varlık türünü (Blog ) başlatır. Tüm ilişkilerde olduğu gibi, bunun yerine bağımlı varlık türüyle (BlogHeader) başlamak tam olarak eşdeğerdir. Örneğin:

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

Bu seçeneklerin hiçbiri diğerinden daha iyi değildir; her ikisi de tam olarak aynı yapılandırmayla sonuçlanır.

İpucu

Hiçbir zaman bir ilişkiyi sorumludan başlayıp bağımlıdan başlayarak iki kez yapılandırmak gerekmez. Ayrıca, bir ilişkinin sorumlu ve bağımlı yarılarını ayrı ayrı yapılandırmaya çalışmak genellikle işe yaramaz. Her ilişkiyi bir uçtan veya diğerinden yapılandırmayı seçin ve yapılandırma kodunu yalnızca bir kez yazın.

İsteğe bağlı bire bir

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

Bu, önceki örnekle aynıdır, ancak yabancı anahtar özelliği ve sorumluya gezinti artık null atanabilir. Bu, bir bağımlı (BlogHeader) yabancı anahtar özelliğini ve gezintisini olarak ayarlayarak hiçbir sorumluyla (Blog) ilişkilendirilemediğinden ilişkiyi null"isteğe bağlı" yapar.

Önemli

C# null atanabilir başvuru türleri kullanılırken, yabancı anahtar özelliği null atanabilirse bağımlı olandan sorumluya gezinti özelliği null atanabilir olmalıdır. Bu durumda, BlogHeader.BlogId null atanabilir, bu nedenle BlogHeader.Blog de null atanabilir olmalıdır. Daha fazla bilgi için bkz . Null Atanabilir Başvuru Türleriyle Çalışma.

Daha önce olduğu gibi, bu ilişki kural tarafından bulunur. Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Birincil anahtar ile birincil anahtar ilişkisi arasında bire bir gerekli

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

Bire çok ilişkilerin aksine, bire bir ilişkinin bağımlı ucu, birincil anahtar özelliğini veya özelliklerini yabancı anahtar özelliği veya özellikleri olarak kullanabilir. Bu genellikle PK-PK ilişkisi olarak adlandırılır. Bu yalnızca sorumlu ve bağımlı türler aynı birincil anahtar türlerine sahip olduğunda ve sonuçta elde edilen ilişki her zaman gerekli olduğunda mümkündür, çünkü bağımlının birincil anahtarı null atanamaz.

Yabancı anahtarın kural tarafından keşfedilmediği bire bir ilişkiler, ilişkinin asıl ve bağımlı uçlarını gösterecek şekilde yapılandırılmalıdır. Bu genellikle çağrısıyla HasForeignKeyyapılır. Örneğin:

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

İpucu

HasPrincipalKey bu amaçla da kullanılabilir, ancak bunu yapmak daha az yaygındır.

çağrısında HasForeignKeyhiçbir özellik belirtilmediğinde ve birincil anahtar uygun olduğunda, yabancı anahtar olarak kullanılır. Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Gölge yabancı anahtarla bire bir gerekli

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

Bazı durumlarda, yabancı anahtarlar ilişki yalnızca nesne odaklı bir şekilde kullanılırken gerekli olmayan veritabanında nasıl temsil edilir bir ayrıntı olduğundan, modelinizde yabancı anahtar özelliği istemeyebilirsiniz. Bununla birlikte, varlıklar örneğin bir kablo üzerinden göndermek üzere seri hale getirilecekse, yabancı anahtar değerleri, varlıklar nesne biçiminde olmadığında ilişki bilgilerini olduğu gibi tutmanın kullanışlı bir yolu olabilir. Bu nedenle, bu amaç için yabancı anahtar özelliklerini .NET türünde tutmak genellikle pragmatiktir. Yabancı anahtar özellikleri özel olabilir, bu da değerinin varlıkla birlikte hareket etmelerine izin verirken yabancı anahtarı açığa çıkarmaktan kaçınmak için genellikle iyi bir risktir.

Önceki örnekten sonra, bu örnek yabancı anahtar özelliğini bağımlı varlık türünden kaldırır. Ancak, birincil anahtarı kullanmak yerine EF'e türünde intadlı BlogId bir gölge yabancı anahtar özelliği oluşturması istenir.

Burada dikkat edilmesi gereken önemli noktalardan biri, C# null atanabilir başvuru türlerinin kullanılmasıdır. Bu nedenle, yabancı anahtar özelliğinin null atanabilir olup olmadığını ve dolayısıyla ilişkinin isteğe bağlı veya gerekli olup olmadığını belirlemek için bağımlıdan sorumluya gezintinin null atanabilirliği kullanılır. Null atanabilir başvuru türleri kullanılmıyorsa, gölge yabancı anahtar özelliği varsayılan olarak null atanabilir olur ve bu da ilişkiyi varsayılan olarak isteğe bağlı hale getirir. Bu durumda, gölge yabancı anahtar özelliğini null atanamaz duruma getirmek ve ilişkiyi gerekli hale getirmek için kullanın IsRequired .

Bu ilişkinin asıl ve bağımlı uçları belirtmek için yeniden yapılandırmaya ihtiyacı vardır:

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

Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Gölge yabancı anahtarla isteğe bağlı bire bir

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

Önceki örnekte olduğu gibi yabancı anahtar özelliği de bağımlı varlık türünden kaldırılmıştır. Ancak, önceki örnekten farklı olarak, C# null atanabilir başvuru türleri kullanıldığından ve bağımlı varlık türündeki gezinti null atanabilir olduğundan bu kez yabancı anahtar özelliği null atanabilir olarak oluşturulur. Bu, ilişkiyi isteğe bağlı hale getirir.

C# null atanabilir başvuru türleri kullanılmadığında, yabancı anahtar özelliği varsayılan olarak null atanabilir olarak oluşturulur. Bu, otomatik olarak oluşturulan gölge özelliklerine sahip ilişkilerin varsayılan olarak isteğe bağlı olduğu anlamına gelir.

Daha önce olduğu gibi, bu ilişkinin sorumlu ve bağımlı uçları belirtmek için bazı yapılandırmalara ihtiyacı vardır:

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

Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Sorumluya gezinti olmadan bire bir

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

Bu örnekte yabancı anahtar özelliği yeniden kullanıma sunulmuştur, ancak bağımlıdaki gezinti kaldırılmıştır.

İpucu

Yalnızca bir gezinti içeren ilişki (biri bağımlıdan sorumluya veya biri sorumludan bağımlıya, ancak ikisi birden değil) tek yönlü ilişki olarak bilinir.

Yabancı anahtar bulunduğundan, bu ilişki kurala göre bulunur ve böylece bağımlı tarafı gösterir. Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

çağrısının WithOne bağımsız değişkeni olmadığına dikkat edin. EF'e ile BlogHeaderBloggezinti olmadığını söylemenin yolu budur.

Yapılandırma, gezinti olmadan varlıktan başlıyorsa, ilişkinin diğer ucundaki varlığın türü genel HasOne<>() çağrı kullanılarak açıkça belirtilmelidir. Örneğin:

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

Sorumluya gezinti olmadan ve gölge yabancı anahtarla bire bir

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

Bu örnek, hem yabancı anahtar özelliğini hem de bağımlıdaki gezintiyi kaldırarak önceki örneklerden ikisini birleştirir.

Daha önce olduğu gibi, bu ilişkinin sorumlu ve bağımlı uçları belirtmek için bazı yapılandırmalara ihtiyacı vardır:

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

Gezinti ve yabancı anahtar adını gerektiği gibi uygun bir çağrıyla açıkça yapılandırmak için IsRequired()IsRequired(false) daha eksiksiz bir yapılandırma kullanılabilir. Örneğin:

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

Bağımlı gezinti olmadan bire bir

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

Önceki iki örnekte sorumludan bağımlılara gezintiler vardı, ancak bağımlı olandan sorumluya gezinti yoktu. Sonraki birkaç örnek için bağımlı üzerindeki gezinti yeniden tanıtılırken, bunun yerine sorumludaki gezinti kaldırılır.

Kural gereği EF bunu bire çok ilişkisi olarak ele alır. Bire bir yapmak için minimum yapılandırma gerekir:

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

WithOne() Bu yönde gezinti olmadığını belirtmek için bağımsız değişken olmadan yeniden çağrıldığını göreceksiniz.

Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Yapılandırma, gezinti olmadan varlıktan başlıyorsa, ilişkinin diğer ucundaki varlığın türü genel HasOne<>() çağrı kullanılarak açıkça belirtilmelidir. Örneğin:

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

Gezintisi olmayan bire bir

Bazen gezinti olmadan bir ilişki yapılandırmak yararlı olabilir. Böyle bir ilişki yalnızca doğrudan yabancı anahtar değeri değiştirilerek işlenebilir.

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

bu ilişki kural tarafından keşfedilmemiştir, çünkü iki türün ilişkili olduğunu gösteren gezinti yoktur. içinde açıkça OnModelCreatingyapılandırılabilir. Örneğin:

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

Bu yapılandırmayla BlogHeader.BlogId , özellik kurala göre yabancı anahtar olarak algılanır ve yabancı anahtar özelliği null atanamaz olduğundan ilişki "gereklidir". yabancı anahtar özelliği null atanabilir hale getirilerek ilişki "isteğe bağlı" yapılabilir.

Bu ilişkinin daha eksiksiz bir açık yapılandırması:

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

Alternatif anahtarla bire bir

Şimdiye kadarki tüm örneklerde, bağımlı üzerindeki yabancı anahtar özelliği sorumludaki birincil anahtar özelliğiyle kısıtlandı. Bunun yerine yabancı anahtar farklı bir özelliğe kısıtlanabilir ve bu da asıl varlık türü için alternatif anahtar olur. Örneğin:

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

EF her zaman kurala göre birincil anahtarla bir ilişki oluşturacağı için bu ilişki kurala göre keşfedilmemiştir. çağrısı kullanılarak HasPrincipalKeyaçıkça OnModelCreating yapılandırılabilir. Örneğin:

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

HasPrincipalKey gezintileri, yabancı anahtar özelliklerini ve gerekli/isteğe bağlı doğayı açıkça yapılandırmak için diğer çağrılarla birleştirilebilir. Örneğin:

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

Bileşik yabancı anahtar ile bire bir

Şimdiye kadarki tüm örneklerde, sorumlunun birincil veya alternatif anahtar özelliği tek bir özellik içermektedir. Birincil veya alternatif anahtarlar da birden fazla özellik biçiminde oluşturulabilir; bunlar "bileşik anahtarlar" olarak bilinir. bir ilişkinin sorumlusu bileşik anahtara sahip olduğunda, bağımlının yabancı anahtarı da aynı sayıda özelliğe sahip bir bileşik anahtar olmalıdır. Örneğin:

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

Bu ilişki kural tarafından bulunur. Ancak, bileşik anahtarlar otomatik olarak bulunamadığından, yalnızca bileşik anahtar açıkça yapılandırıldıysa bulunur. Örneğin:

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

Önemli

Bileşik yabancı anahtar değeri, özellik değerlerinden herhangi biri null olduğunda kabul edilir null . Bir özelliği null olan ve null olmayan başka bir bileşik yabancı anahtar, aynı değerlere sahip bir birincil veya alternatif anahtar için eşleşme olarak kabul edilmez. Her ikisi de olarak kabul nulledilir.

Hem hem HasPrincipalKey de HasForeignKey birden çok özelliğe sahip anahtarları açıkça belirtmek için kullanılabilir. Örneğin:

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

İpucu

Yukarıdaki kodda ve çağrıları HasKeyHasOne iç içe yerleştirilmiş bir oluşturucuda birlikte gruplandırılmıştır. İç içe oluşturucular aynı varlık türü için birden çok kez çağırma Entity<>() gereksinimini ortadan kaldırır, ancak işlevsel olarak birden çok kez çağırmaya Entity<>() eşdeğerdir.

Art arda silme olmadan bire bir gerekli

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

Kural gereği, gerekli ilişkiler art arda silmek üzere yapılandırılır. Bunun nedeni, sorumlu silindikten sonra bağımlının veritabanında bulunamamasıdır. Veritabanı, artık mevcut olmayan bağımlı satırları otomatik olarak silmek yerine genellikle uygulamayı kilitleyen bir hata oluşturacak şekilde yapılandırılabilir. Bunun için bazı yapılandırmalar gerekir:

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

Kendi kendine başvuruda bulunan bire bir

Önceki tüm örneklerde, asıl varlık türü bağımlı varlık türünden farklıydı. Böyle olması gerekmez. Örneğin, aşağıdaki türlerde her Person biri isteğe bağlı olarak başka bir Personile ilişkilidir.

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
}

Bu ilişki kural tarafından bulunur. Gezintilerin, yabancı anahtarın veya ilişkinin gerekli/isteğe bağlı doğasının kurala göre keşfedilmediği durumlarda, bu öğeler açıkça yapılandırılabilir. Örneğin:

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

Not

Bire bir kendi kendine başvuran ilişkilerde, sorumlu ve bağımlı varlık türleri aynı olduğundan, yabancı anahtarı içeren türün belirtilmesi bağımlı ucu netleştirmez. Bu durumda, bağımlı olandan sorumluya olan noktalarda HasOne belirtilen gezinti ve sorumludan bağımlıya doğru noktalarda WithOne belirtilen gezinti.