5

Molto semplicemente sto utilizzando il codice Entity Framework 4.1 e desidero sostituire i miei attributi [ForeignKey (..)] con chiamate fluenti su modelBuilder. Qualcosa di simile a WithRequired (..) e HasForeignKey (..) sotto cui legare una proprietà di chiave esterna esplicita (CreatedBySessionId) insieme alla proprietà di navigazione associata (CreatedBySession). Ma mi piacerebbe fare questo per un 1-1 relationsip invece di un uno a molti:EF 4.1 Codice Primo modelloBuilder HasForeignKey per relazioni uno a uno

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

un esempio più concreto è al di sotto. Funziona abbastanza felicemente con l'attributo [ForeignKey (..)] ma mi piacerebbe farla finita e configurarla esclusivamente su modelbuilder.

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

Ecco una sessione può essere responsabile della creazione di molti VendorApplications (Session.Applications), ma una sessione sta lavorando su al più una VendorApplication alla volta (Session.CurrentApplication). Vorrei legare la proprietà CurrentApplicationId con la proprietà di navigazione CurrentApplication in modelBuilder anziché tramite l'attributo [ForeignKey (..)].

Le cose che ho provato

Quando si rimuove il [ForeignKey (..)] attribuiscono la proprietà CurrentApplication genera una colonna CurrentApplication_VendorApplicationId nel database che non è legato alla colonna CurrentApplicationId.

Ho provato in modo esplicito la mappatura del rapporto utilizzando il nome della colonna CurrentApplicationId come sotto, ma ovviamente questo genera un errore perché il nome della colonna del database "CurrentApplicationId" è già in uso dalla struttura Session.CurrentApplicationId:

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

Sembra che manchi qualcosa di molto ovvio qui poiché tutto ciò che voglio fare è eseguire la stessa operazione che fa [ForeignKey (..)] all'interno del generatore di modelli. O è un caso che questa è una cattiva pratica ed è stata esplicitamente tralasciata?

risposta

10

È necessario mappare la relazione come uno-a-molti e omettere la proprietà della raccolta nella relazione.

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

Sì, questo è tutto! Avevo effettivamente giocato con quella configurazione in precedenza, ma EF ha gettato un'eccezione di conflitto di molteplicità, quindi ho stabilito che la relazione doveva essere 1: 1. Naturalmente ora mi rendo conto che il conflitto di molteplicità in realtà è avvenuto perché inizialmente avevo CurrentApplicationId come non annullabile ... ** (face palm) **. Grazie per l'aiuto, molto apprezzato! – Walter

Problemi correlati