Bir ilişkilendirmenin asıl sonu, Varlık çerçevesinde 1: 1 ilişkide ne anlama gelir?


269
public class Foo
{
    public string FooId{get;set;}
    public Boo Boo{get;set;}
}


public class Boo
{
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

Hata aldığımda Entity Framework bunu yapmaya çalışıyordu:

'ConsoleApplication5.Boo' ve 'ConsoleApplication5.Foo' türleri arasındaki ilişkilendirmenin ana sonu belirlenemiyor. Bu ilişkilendirmenin ana ucu, ilişki akıcı API'si veya veri ek açıklamaları kullanılarak açıkça yapılandırılmalıdır.

Bu hata için bir çözüm ile StackOverflow ile ilgili sorular gördüm, ama "asıl son" teriminin ne anlama geldiğini anlamak istiyorum.


Yanıtlar:


378

Birebir ilişkide bir uç asıl olmalı ve ikinci uç bağımlı olmalıdır. Asıl son, önce eklenecek ve bağımlı olan olmadan var olabilecek sondur. Bağımlı son, anapara yabancı anahtar olması nedeniyle anaparadan sonra eklenmesi gereken sondur.

Bağımlı olan FK varlık çerçevesi olması durumunda PK'sı da olmalıdır, bu durumda aşağıdaki durumlarda kullanmalısınız:

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

Veya akıcı haritalama

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);

6
@Ladislav, her ikisinin de (bire bir) isteğe bağlı bir referansı olan iki bağımsız tablo yapmam gerekiyor, her ikisinin de kendi PK'ları olmasını istiyorum, bu nasıl mümkün olabilir? Ayrı bir soru gönderdim .
Shimmy Weitzhandler

10
Bu sorunun cevabını bulmak için kaç saat harcadığınız hakkında hiçbir fikriniz yok - ms dokümantasyon POOOOOOP ty.
gangelo

1
System.ComponentModel.DataAnnotations.Schema kullanarak eklemeniz gerekebileceğini unutmayın; 'de ForeignKey almak için nasıl
stuartdotnet

2
Bu, o Foozaman müdürün bu olduğu anlamına mı geliyor ?
bflemi3

8
@ bflemi3 doğru Booolduğunuz bağımlı, a gerektirir Foove yabancı anahtarı alır. Fooprensiptir ve a olmadan var olabilir Boo.
Colin

182

Bunu [Required]çözmek için veri notu özelliğini de kullanabilirsiniz :

public class Foo
{
    public string FooId { get; set; }

    public Boo Boo { get; set; }
}

public class Boo
{
    public string BooId { get; set; }

    [Required]
    public Foo Foo {get; set; }
}

Fooiçin gereklidir Boo.


Bu, aşağıdaki kod için doğruydu, burada ayrı bir varlık olarak ikisinin arasında bir ortak sınıf kamu sınıfı Organizasyon {public int Id {get; Ayarlamak; }} ortak sınıf kullanıcısı {public int Id {get; Ayarlamak; }} ortak sınıf UserGroup {[Key] public int Id {get; Ayarlamak; } [Gerekli] genel sanal Organizasyon Organizasyonu {get; Ayarlamak; } [Zorunlu] genel sanal Kullanıcı Kullanıcı {get; Ayarlamak; }}
AndyM

Oracle kullanıyorum ve akıcı api'lerin hiçbiri benim için çalışmadı. Sağ ol, kanka. Çok basit.
CameronP

11
Bu çözümü kullanırken Boo, Foomülkün tembel yükünü ilk tetiklemediğiniz sürece, veritabanından yeni aldığınız bir güncellemeyi denediğinizde ve güncellerken deneme istisnaları alacağınızı unutmayın . entityframework.codeplex.com/SourceControl/network/forks/…
NathanAldenSr

2
o Boo Boozaman sanal olmamalı mı?
Simon_Weaver

1
@NathanAldenSr bağlantı şimdi kötü, bu değişikliği nasıl yapıyorsunuz?
CamHart

9

Bu, @Ladislav Mrnka'nın bire bir ilişkiyi yapılandırmak için akıcı api kullanma cevabına atıfta bulunuyor.

Sahip olduğu bir durum vardı FK of dependent must be it's PK mümkün olmadığı .

Örneğin, Foozaten bire-çok ilişkisi var Bar.

public class Foo {
   public Guid FooId;
   public virtual ICollection<> Bars; 
}
public class Bar {
   //PK
   public Guid BarId;
   //FK to Foo
   public Guid FooId;
   public virtual Foo Foo;
}

Şimdi, Foo ve Bar arasında birebir bir ilişki daha eklemek zorunda kaldık.

public class Foo {
   public Guid FooId;
   public Guid PrimaryBarId;// needs to be removed(from entity),as we specify it in fluent api
   public virtual Bar PrimaryBar;
   public virtual ICollection<> Bars;
}
public class Bar {
   public Guid BarId;
   public Guid FooId;
   public virtual Foo PrimaryBarOfFoo;
   public virtual Foo Foo;
}

Akıcı api kullanarak bire bir ilişki nasıl belirtileceği aşağıda açıklanmıştır:

modelBuilder.Entity<Bar>()
            .HasOptional(p => p.PrimaryBarOfFoo)
            .WithOptionalPrincipal(o => o.PrimaryBar)
            .Map(x => x.MapKey("PrimaryBarId"));

PrimaryBarIdEklerken, akıcı API ile belirttiğimiz için kaldırılması gerektiğini unutmayın .

Ayrıca yöntem adının [WithOptionalPrincipal()][1]biraz ironik olduğunu da unutmayın . Bu durumda Müdür Bar'dır. Msdn'deki WithOptionalDependent () açıklaması bunu daha açık hale getirir.


2
Ne Aslında eğer istediğinizPrimaryBarId özelliği? Bu benim için çok saçma. Özelliği ekleyip yabancı anahtar olduğunu söylersem, bir hata alıyorum. Ama mülküm yoksa, EF yine de onu yaratacaktır. Fark ne?
Chris Pratt

1
@ChrisPratt Bu makul görünmeyebilir. İz ve hatadan sonra bu çözümlere vardım. Ben varken bire bir eşleme yapılandırmak mümkün değildi PrimayBarIdtesisle Foovarlık. Muhtemelen denediğiniz aynı çözüm. Belki EF'deki sınırlamalar?
Sudarshan_SMD

3
Evet o. EF'in bugüne kadar hiçbir zaman benzersiz dizinler uygulamadığını öğrendim. Sonuç olarak, bire bir eşleştirmenin tek yolu, ana sonun birincil anahtarını bağımlı sonun birincil anahtarı olarak kullanmaktır, çünkü birincil anahtar doğaya özgüdür. Başka bir deyişle, bunu yarı-uyguladılar ve tablolarınızın standart olmayan bir şekilde tasarlanması gerektiğini belirten bir kısayol aldılar.
Chris Pratt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.