2016-05-05 7 views
2

Ich verfolge diese Frage: EF Code First - 1-to-1 Optional RelationshipOne-to-One optional Beziehung mit beiden Enden optional und beide FKs

Und ich habe meine Beziehungen setzen sich wie folgt zusammen:

public class Review { 
    [Key] 
    public int ReviewId { get; set; } 

    public virtual Payment Payment { get; set; } 
} 

public class Payment { 
    [Key] 
    public int PaymentId { get; set; } 

    [ForeignKey("Review")] 
    public int? ReviewId { get; set; } 
    public virtual Review Review { get; set; } 
} 

    public class ReviewConfiguration : EntityTypeConfiguration<Review> 
{ 
    public ReviewConfiguration() 
    { 
     // One-to-One Optional 
     HasOptional<Payment>(s => s.Payment).WithOptionalDependent(s => s.Review).Map(s => s.MapKey("PaymentId")); 
    } 
} 

Und ich ONE erhalten der Schlüssel gültig ist, aber das andere ist nie als optionales FK abgebildet:

enter image description here

Was mache ich falsch?

Ich habe einige seltsame Hacky-Lösungen gesehen, die das Erstellen leerer Listen usw. beinhalten - nicht das, wonach ich suche. Ich bin auf der Suche nach einem richtigen Ansatz hier - es hat zu existieren ... richtig?

aktualisieren

ich die oben jetzt mit - wenn ich die Zahlung auf der Hand und brauchen die Bewertung zuzugreifen oder zu löschen, ich habe eine andere Lookup auf dem [pseudo-FK] ReviewId zu tun, was total scheiße ist.

+0

Dies kann nicht Ihr Modell + Mapping sein. Es gibt Fehler * Die Navigationseigenschaft "Review", die für den Typ "Zahlung" deklariert wurde, wurde mit in Konflikt stehenden Fremdschlüsseln konfiguriert. * –

+0

@GertArnold genau so habe ich es. Einfach doppelt und dreifach überprüft. Haben Sie PaymentId bei Überprüfung? Ich nicht. Danke, dass du es übrigens ausprobiert hast. Extrem frustrierendes Zeug. – RobVious

+0

Seltsam. Sowieso. EF benötigt die FK ReviewId nicht. Mit der einen optionalen FK PaymentId weiß es genug, um die Assoziation bidirektional aufzubauen. –

Antwort

4

In jeder Eins-zu-Eins-Zuordnung verwendet EF nur einen Fremdschlüssel. Wenn die Zuordnung erforderlich ist, ist der Fremdschlüssel auch der Primärschlüssel der abhängigen Entität, wie in here erläutert.

Wenn die Zuordnung optional ist, sollten beide Entitäten unabhängig voneinander existieren können. Daher können ihre Primärschlüssel keine Fremdschlüssel sein, da PKs nicht optional sein können. Hier ist ein zusätzliches Nullable-FK-Feld erforderlich, um die optionale Zuordnung herzustellen.

In Ihrem Fall technisch es spielt eigentlich keine Rolle, welches Unternehmen hat das FK-Feld (logisch, kann es).

public class Review 
{ 
    [Key] 
    public int ReviewId { get; set; } 
    public virtual Payment Payment { get; set; } 
} 

public class Payment 
{ 
    [Key] 
    public int PaymentId { get; set; } 

    public Review Review { get; set; } 
} 

Mit dieser Abbildung: Ich habe dieses Modell

public class ReviewConfiguration : EntityTypeConfiguration<Review> 
{ 
    public ReviewConfiguration() 
    { 
     // One-to-One Optional 
     HasOptional(s => s.Payment) 
      .WithOptionalDependent(s => s.Review) 
      .Map(s => s.MapKey("PaymentId")); 
    } 
} 

(also abgesehen von Payment.ReviewId, dies ist identisch mit dem Modell + Mapping in Ihrer Frage).

Jetzt kann ich Dinge wie ...

db.Set<Review>().Add(new Review { Payment = new Payment() }); 
db.Set<Payment>().Add(new Payment { Review = new Review() }); 
db.SaveChanges(); 

... wo db natürlich ein Zusammenhang.Der Inhalt der beiden Tabellen ist jetzt:

PaymentId 
----------- 
1 
2 

ReviewId PaymentId 
----------- ----------- 
1   1 
2   2 

Und ich die Daten in zwei Richtungen wie so abfragen:

var data = db.Set<Review>().Include(r => r.Payment).ToList(); 

oder

var data = db.Set<Payment>().Include(r => r.Review).ToList(); 

Aber statt ReviewConfiguration, ich kann auch verwendet werden. ..

public class PaymentConfiguration : EntityTypeConfiguration<Payment> 
{ 
    public PaymentConfiguration() 
    { 
     // One-to-One Optional 
     HasOptional(s => s.Review) 
      .WithOptionalDependent(s => s.Payment) 
      .Map(s => s.MapKey("ReviewId")); 
    } 
} 

Jetzt wird es ein FK-Feld ReviewId in Tabelle Payment geben, und der Rest des Codes funktioniert ohne Änderungen.

+0

Vielen Dank Meine einzige Sorge ist, dass db.SaveChanges() füllt das NULL-fähige nicht-primäre FK am anderen Ende nicht aus - aber ich muss das testen s wieder aus. – RobVious

+0

Mach dir keine Sorgen, tut es.EF speichert zunächst die Principal Entity und verwendet dann seinen generierten PK-Wert, um das FK-Feld in der abhängigen Entität zu setzen, alles unter den Deckungen (und natürlich alle in einer Transaktion). –

+0

Vielen Dank noch einmal Leute. Ich weiß, das hat einige Zeit gedauert. – RobVious

1

Sie müssen Tippfehler in Ihren Modellen haben (2 ReviewId Felder in Zahlung?). Wenn Sie den fließenden Weg gehen, fügen Sie keine Beziehungsattribute hinzu, um die Dinge zu verwirren. IAC, versuchen Sie etwas wie folgt:

public class Review { 
    public int ReviewId { get; set; } 

    public int? PaymentId { get; set; } 
    public virtual Payment Payment { get; set; } 
} 

public class Payment { 
    public int PaymentId { get; set; } 

    public int? ReviewId { get; set; } 
    public virtual Review Review { get; set; } 
} 

public class ReviewConfiguration : EntityTypeConfiguration<Review> 
{ 
    public ReviewConfiguration() 
    { 
     HasOptional(r => r.Payment) 
      .WithMany() 
      .HasForeignKey(r => r.PaymentId); 
    } 
} 

public class PaymentConfiguration : EntityTypeConfiguration<Payment> 
{ 
    public PaymentConfiguration() 
    { 
     HasOptional(p => p.Review) 
      .WithMany() 
      .HasForeignKey(p => p.ReviewId); 
    } 
} 
+0

Danke dafür. Ich habe meine Modelle beim Kopieren/Einfügen abgeschliffen - korrigiert. Ich werde das versuchen und mit Ergebnissen zurückschreiben. Danke, Steve. – RobVious

+0

Ich bekomme hier Folgendes: PaymentId: Name: Jeder Eigenschaftsname in einem Typ muss eindeutig sein. Der Name der Eigenschaft "PaymentId" ist bereits definiert. ReviewId: Name: Jeder Eigenschaftsname in einem Typ muss eindeutig sein. Der Eigenschaftenname 'ReviewId' ist bereits definiert. – RobVious

+0

Ich habe so viele Änderungen an dem, was Sie hier haben, und nichts funktioniert. Downvoting für Ungenauigkeit, aber wird korrigiert, wenn wir etwas finden, das funktioniert. – RobVious