5

Muy simple, estoy usando primero el código Entity Framework 4.1 y me gustaría reemplazar mis atributos [ForeignKey (..)] con llamadas fluidas en modelBuilder en su lugar. Algo similar a WithRequired (..) y HasForeignKey (..) a continuación, que vincula una propiedad de clave externa explícita (CreatedBySessionId) junto con la propiedad de navegación asociada (CreatedBySession). Pero me gustaría hacer esto por una una a una relationsip en lugar de uno a muchos:EF 4.1 Código First ModelBuilder HasForeignKey para relaciones One to One

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

Un ejemplo más concreto es abajo. Esto funciona bastante feliz con el atributo [ForeignKey (..)], pero me gustaría eliminarlo y configurarlo exclusivamente en el modelo.

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

Aquí una sesión puede ser responsable de la creación de muchos VendorApplications (Session.Applications), pero hay una sesión de trabajo en a lo sumo un VendorApplication a la vez (Session.CurrentApplication). Me gustaría vincular la propiedad CurrentApplicationId con la propiedad de navegación CurrentApplication en modelBuilder en lugar de hacerlo mediante el atributo [ForeignKey (..)].

cosas que he intentado

Cuando se quita el [ForeignKey (..)] atribuyen la propiedad CurrentApplication genera una columna CurrentApplication_VendorApplicationId en la base de datos que no está atado a la columna de CurrentApplicationId.

He tratado de forma explícita la cartografía de la relación con el nombre de la columna CurrentApplicationId como abajo, pero, obviamente, esto genera un error debido a que el nombre de la columna de base de datos "CurrentApplicationId" ya está siendo utilizado por la propiedad Session.CurrentApplicationId:

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

Parece que aquí me falta algo muy obvio, ya que todo lo que quiero hacer es realizar la misma operación que [ForeignKey (..)] pero dentro del generador de modelos. ¿O es un caso que esta es una mala práctica y se dejó de lado explícitamente?

Respuesta

10

Debe asignar la relación como uno a varios y omitir la propiedad de recopilación en la relación.

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

Sí eso es todo! En realidad, había jugado antes con esa configuración, pero EF lanzó una excepción de conflictos de multiplicidad, así que determiné que la relación tenía que ser de 1: 1. Por supuesto ahora me doy cuenta de que el conflicto de multiplicidad realmente sucedió porque originalmente tenía CurrentApplicationId como no anulable ... ** (cara de palma) **. ¡Gracias por la ayuda, muy apreciada! – Walter

Cuestiones relacionadas