2016-08-19 7 views
0

Ich habe Payments und Reviews.EF Eins-zu-Eins optionale Navigationseigenschaften der Beziehung funktioniert nicht

public class Payment { 

     [Key] 
     [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
     public int PaymentId { get; set; } 

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

     // other properties 
} 

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

     [ForeignKey("PeerPayment")] 
     public int? PeerPaymentId { get; set; } 
     public virtual PeerPayment PeerPayment { get; set; } 
} 

ich sie abgebildet haben, wie folgt:

public ReviewConfiguration() { 
     // One-to-One optional:optional 
     HasOptional(s => s.Payment).WithMany().HasForeignKey(x => x.PaymentId); 
    } 

    public PaymentConfiguration() { 
     // One-to-One optional:optional 
     HasOptional(s => s.Review).WithMany().HasForeignKey(s => s.ReviewId); 
    } 

Meine Datenbank FKs als nullable, geschaffen, die groß ist. Der folgende Test schlägt jedoch fehl:

public async Task ReviewPeerPaymentWorks() { 
     using (var db = new AppContext()) { 
      var user1 = db.FindUser("M1"); 
      var user2 = db.FindUser("M2"); 
      var review = new Review() { 
       FromUserId = user1.UserId, 
       ToUserId = user2.UserId 
      }; 
      db.Reviews.Add(review); 
      var payment = new Payment() { 
       FromUserId = user1.UserId, 
       ToUserId = user2.UserId, 
       ReviewId = review.ReviewId 
      }; 
      db.Payments.Add(payment); 
      db.SaveChanges(); 

      review = db.Reviews.First(s => s.ReviewId == review.ReviewId); 
      payment = db.Payments.First(s => s.PaymentId == payment.PaymentId); 
      Assert.AreEqual(review.PaymentId, payment.PaymentId); // fails - review.PaymentId is always null 
      Assert.AreEqual(review.ReviewId, payment.ReviewId); // passes 
      Assert.AreEqual(review.Payment.PaymentId, payment.Review.PaymentId); // fails - review.Payment is null, payment.Review.PaymentId is null 
     } 
    } 

Was mache ich falsch?

Um klar zu sein - ich möchte meinen Test nicht ändern, es sei denn jemand denkt, dass es ein ungültiger Weg ist, die Beziehung aus irgendeinem Grund zu testen.

+0

[DatabaseGeneratedAttribute (DatabaseGeneratedOption.Identity)] fügen Sie diese Anmerkung in PaymentID Feld Zahltisch auch –

+1

wieder, mischen Sie 'DataAnnotations' mit 'Fließende API'. warum so? Du hast auch gesagt, dass das eine Eins-zu-Eins-Beziehung ist. Aber Sie konfigurieren "Eins-zu-viele". In 'eins-zu-eins'-Beziehungen ist PK bei beiden gleich. –

+0

@AdilMammadov aber beide Entitäten können unabhängig voneinander erstellt werden. Wie konfiguriere ich das so, dass beide Seiten optional sind? – RobVious

Antwort

1

One-to-One-Beziehung ist ein bisschen schwierig in der EF. Vor allem in Code-First. In der DB-First würde ich die UNIQUE-Einschränkung für die beiden FK-Eigenschaften machen, um sicherzustellen, dass diese Beziehung nur einmal pro Tabelle erscheint (aber bitte sicherstellen, dass es nicht One-to-One-oder-Zero ist, weil UNIQUE constraint erlauben wird Sie haben nur einen NULL FK Wert). Im Falle der NULL-fähigen FK kann dies über die 3. Relationstabelle mit der UNIQUE-Einschränkung über alle Spalten in der Relationstabelle erfolgen. Hier

ist die URL, die erklärt, wie EF die Beziehung One-to-One-Karten: http://www.entityframeworktutorial.net/entity-relationships.aspx
Hier ist die URL, die erklärt, wie One-to-One-Beziehung konfigurieren: http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

Im Allgemeinen schlagen sie vor, zu verwenden, die gleichen PK-Werte für beide Tabellen:

„so müssen wir über Einheiten so konfigurieren, dass EF Studenten und StudentAddresses Tabelle in der DB schafft, wo es StudentID in Tabelle Student als PK machen und StudentAddressId Spalte in StudentAddress Tabelle als PK und FK beide. "

Ich habe Ihr Beispiel versucht und Sie haben zwei unabhängige Eins-zu-viele-Beziehungen zwischen Überprüfung und Zahlung. Aber ohne die Navigationseigenschaft "Viele". Blick WithMany():

.HasOptional(s => s.Review).WithMany().HasForeignKey(s => s.ReviewId); 

So ist es echte One-To-Many Beziehung ohne VIELE (List) Navigationseigenschaften. Schauen Sie sich die MSSQL Diagramm:

MSSQL diagram

Und der Grund, warum haben Sie die NULL-Werte erhalten - weil Sie Payment.ReviewId Beziehung zugewiesen und hat zuweisen nicht die Review.PaymentId Beziehung. Aber du hast erwartet, dass EF es automatisch gemacht hat.Da sie getrennte Beziehungen sind - links EF eine der als NULL, weil Sie es nicht zugewiesen haben

+0

Danke - aber beide Entitäten können unabhängig voneinander erstellt werden, also welche PK verwende ich? – RobVious

+0

Es scheint, dass es keine Möglichkeit gibt, sie gleichzeitig unabhängig voneinander zu erstellen. Sie müssen sie zusammen erstellen oder mindestens einen von ihnen aus db lesen. Sie sollten den Weg mit der Relationstabelle mit beiden einzigartigen FK betrachten. In diesem Fall werden die Entitäten erst dann verknüpft, wenn Sie die Beziehung erstellen. Es sollte eine Möglichkeit geben, dies zuerst mit dem Code zu tun – Sergey

0
public async Task ReviewPeerPaymentWorks() { 
    using (var db = new AppContext()) { 
     var user1 = db.FindUser("M1"); 
     var user2 = db.FindUser("M2"); 
     var review = new Review() { 
      FromUserId = user1.UserId, 
      ToUserId = user2.UserId 
     }; 
     db.Reviews.Add(review); 
     var payment = new Payment() { 
      FromUserId = user1.UserId, 
      ToUserId = user2.UserId, 
      ReviewId = review.ReviewId 
     }; 

     db.Payments.Add(payment); 
     db.SaveChanges(); 
     review.Payment = payment; 
     db.SaveChanges(); 


     review = db.Reviews.First(s => s.ReviewId == review.ReviewId); 
     payment = db.Payments.First(s => s.PaymentId == payment.PaymentId); 
     Assert.AreEqual(review.PaymentId, payment.PaymentId); // fails - review.PaymentId is always null 
     Assert.AreEqual(review.ReviewId, payment.ReviewId); // passes 
     Assert.AreEqual(review.Payment.PaymentId, payment.Review.PaymentId); // fails - review.Payment is null, payment.Review.PaymentId is null 
    } 
} 
+0

Ich möchte meinen Test nicht ändern, damit er bestanden wird. Ich möchte herausfinden, warum meine Modellierungs- und Navigationseigenschaften nicht wie erwartet funktionieren. – RobVious

-1

Ich habe dieses Problem zweimal konfrontiert. Jedes Mal habe ich diese beiden Elemente aus Edmx entfernt und neu hinzugefügt. Es löst mein Problem.

Hoffentlich wird es mit Ihnen zusammenarbeiten

+0

Ich denke, er verwendet Code zuerst. und es gibt keine edmx-datei wäre da. –

Verwandte Themen