5

Ganz einfach verwende ich zuerst Entity Framework 4.1 Code und möchte stattdessen meine [ForeignKey (..)] Attribute durch fließende Aufrufe auf modelBuilder ersetzen. Ähnlich wie WithRequired (..) und HasForeignKey (..), die eine explizite Fremdschlüsseleigenschaft (CreatedBySessionId) mit der zugehörigen Navigationseigenschaft (CreatedBySession) verknüpfen. Aber ich möchte dieses 00.59 relationsip für eine tun, statt eins zu viele:EF 4.1 Code First ModelBuilder HasForeignKey für One-to-One-Beziehungen

modelBuilder.Entity<..>().HasMany(..).WithRequired(x => x.CreatedBySession).HasForeignKey(x => x.CreatedBySessionId) 

Ein konkretes Beispiel ist unten. Das funktioniert ziemlich gut mit dem [ForeignKey (..)] -Attribut, aber ich möchte es weglassen und es rein auf Modelbuilder konfigurieren.

public class VendorApplication 
{ 
    public int VendorApplicationId { get; set; } 

    public int CreatedBySessionId { get; set; } 
    public virtual Session CreatedBySession { get; set; } 
} 

public class Session 
{ 
    public int SessionId { get; set; } 

    [ForeignKey("CurrentApplication")] 
    public int? CurrentApplicationId { get; set; } 
    public virtual VendorApplication CurrentApplication { get; set; } 

    public virtual ICollection<VendorApplication> Applications { get; set; } 
} 

public class MyDataContext: DbContext 
{ 
    public IDbSet<VendorApplication> Applications { get; set; } 
    public IDbSet<Session> Sessions { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Session>().HasMany(x => x.Applications).WithRequired(x => x.CreatedBySession).HasForeignKey(x => x.CreatedBySessionId).WillCascadeOnDelete(false); 
     // Note: We have to turn off Cascade delete on Session <-> VendorApplication relationship so that SQL doesn't complain about cyclic cascading deletes 
    } 
} 

Hier eine Session kann für die Erstellung von vielen VendorApplications (Session.Applications) verantwortlich sein, aber eine Session arbeitet an höchstens einem VendorApplication zu einem Zeitpunkt (Session.CurrentApplication). Ich möchte die CurrentApplicationId-Eigenschaft mit der CurrentApplication-Navigationseigenschaft in ModelBuilder verknüpfen, anstatt über das [ForeignKey (..)] - Attribut.

Dinge, die ich habe Versuchte

Wenn Sie den [ForeignKey (..)] entfernen das Attribut CurrentApplication Eigenschaft erzeugt eine CurrentApplication_VendorApplicationId Spalte in der Datenbank, die an die CurrentApplicationId Spalte nicht gebunden ist.

Ich habe versucht, explizit die Beziehung Abbilden der CurrentApplicationId Spaltennamen verwenden, wie unten, aber offensichtlich das einen Fehler erzeugt, da die Datenbank Spaltenname „CurrentApplicationId“ wird bereits von der Unterkunft Session.CurrentApplicationId verwendet:

modelBuilder.Entity<Session>().HasOptional(x => x.CurrentApplication).WithOptionalDependent().Map(config => config.MapKey("CurrentApplicationId")); 

Es fühlt sich an, als würde ich hier etwas sehr Offensichtliches vermissen, da ich nur die gleiche Operation ausführen will, die [ForeignKey (..)] ausführt, aber innerhalb des Modell-Builders. Oder ist das eine schlechte Praxis und wurde explizit weggelassen?

Antwort

10

Sie müssen die Beziehung als Eins-zu-viele zuordnen und die Auflistungseigenschaft in der Beziehung auslassen.

modelBuilder.Entity<Session>() 
    .HasOptional(x => x.CurrentApplication) 
    .WithMany() 
    .HasForeignKey(x => x.CurrentApplicationId) 
+1

Ja das ist es! Ich hatte tatsächlich früher mit dieser Konfiguration herumgespielt, aber EF hat eine Multiplizität-Konflikt-Ausnahme ausgelöst, so dass ich feststellte, dass die Beziehung 1: 1 sein musste. Natürlich merke ich jetzt, dass der Multiplizitätskonflikt tatsächlich passierte, weil ich ursprünglich CurrentApplicationId als nicht nullable ... ** (Gesichtspalme) ** hatte. Danke für die Hilfe, sehr geschätzt! – Walter

Verwandte Themen