Entity Framework 6 Fluent Api Configuración de una relación a una
[Table("Child", Schema = "dbo")]
public partial class Child
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
public int? Parent1Id { get; set; }
public int? Parent2Id { get; set; }
public virtual Parent Parent1 {get; set}
public virtual Parent Parent2 {get; set}
}
[Table("Parent", Schema = "dbo")]
public partial class Parent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
public virtual Child Child1 { get; set; }
public virtual Child Child2 { get; set; }
//modelBuilder below would work if I had this
//public virtual ICollection Child1 { get; set; }
}
Esto significa ser una relación entre pariente y niño. Parent1Id y Parent2 Es nulo.
Sólo encontré ejemplos (con FluentAPI) para una relación de uno a muchos y si tuviera una colección de Child in Parent tendría que hacer algo como:
modelBuilder.Entity()
.HasMany(e => e.Child1)
.WithOptional(e => e.Parent1)
.HasForeignKey(e => e.Parent1Id);
modelBuilder.Entity()
.HasMany(e => e.Child2)
.WithOptional(e => e.Parent2)
.HasForeignKey(e => e.Parent2Id);
El niño tendrá un pariente de referencia FK. El pariente no tiene hijos de referencia FK.
Mi pregunta es, ¿cómo puedo hacer esto como una relación uno a uno usando EF 6.x? Vi el método HasOne() pero eso es de EFCore así que estoy fuera de opciones en este.
Gracias.
Pregunta hecha hace 3 años, 5 meses, 4 días - Por scriptsculptor
5 Respuestas:
-
Nota: Las relaciones individuales no son técnicamente posibles en MS SQL Server. Estas siempre serán relaciones de uno a cero o uno. EF forma relaciones de uno a uno en entidades no en el DB.
https://www.entityframeworktutorial.net/code-first/configure-one-to-relationship-in-code-first.aspx
Respondida el Dec 18, 2020 a las 19:33 - por binarybard
Votos positivos: 0 | Votos negativos: 0 -
EF6 admite naturalmente sólo relaciones individuales usando el llamado asociaciones principales comunes, donde el PK dependiente también se utiliza como FK. Sin embargo no son aplicables en este escenario (cuando usted necesita más de una relación entre dos entidades). Así que necesitas relaciones basadas en un solo FK.
Son compatibles, pero con las siguientes restricciones:
- EF6 no creará la limitación/índice única en la columna FK necesaria para ejecutar "a 1" (o "a 0 o 1") en la base de datos, por lo que desde el punto de vista de la base de datos serán uno a otro.
- No se admiten propiedades explícitas FK (nota la falta de
HasForeignKey
API fluida al configurar una relación entre uno y uno). Tienes que eliminarlos y trabajar sólo con propiedades de navegación. El FK columna nombre se puede especificar utilizandoMapKey
dentroMap
método.
Usted tiene que aceptar estas restricciones, de lo contrario no puede utilizar EF6 con tal modelo.
Comience eliminando las propiedades explícitas de FK del modelo:
// remove these: //public int? Parent1Id { get; set; } // //public int? Parent2Id { get; set; }
Lo siguiente a considerar es que las relaciones EF siempre consideran uno de los lados siendo principal, y el otro siendo dependiente. En un solo lado el lado "uno" es siempre el principal, y el lado "muchos" es siempre el dependiente. Para uno a uno normalmente necesarios el fin es el principal, y opcional el fin es el dependiente, pero cuando ambos extremos son requeridos o ambos extremos son opcionales (como en su caso), tiene que especificar que mediante el uso adecuado
WithRequired
/WithOptional
método, dondePrincipal
/Dependent
sufijo especifica cómo tratar la entidad siendo configurado (el argumento tipo genérico alHas
método). Esto es importante y suele confundir a la gente, porque el resto de la configuración fluida dentroMap
aplica siempre a la entidad dependiente, independientemente de cuál entidad se esté utilizando para iniciar la configuración.Con eso dicho, en su muestra hay dos relaciones, ambas con
Parent
siendo el principal,Child
ser el dependiente, y ambos fines es opcional. Por lo tanto, la configuración fluida podría sermodelBuilder.Entity
() .HasOptional(p => p.Child1) .WithOptionalPrincipal(c => c.Parent1) .Map(c => c.MapKey("Parent1Id")); modelBuilder.Entity () .HasOptional(p => p.Child2) .WithOptionalPrincipal(c => c.Parent2) .Map(c => c.MapKey("Parent2Id")); También podría configurarse de otra manera:
modelBuilder.Entity
() .HasOptional(c => c.Parent1) .WithOptionalDependent(p => p.Child1) .Map(c => c.MapKey("Parent1Id")); modelBuilder.Entity () .HasOptional(c => c.Parent2) .WithOptionalDependent(p => p.Child2) .Map(c => c.MapKey("Parent2Id")); Nota: Use uno u otro, no ambos. Generalmente la configuración de la relación comienza desde el final teniendo propiedad de navegación (ya que es necesario para
Has
métodos), pero cuando ambos extremos tienen navegación, entonces es sólo una cuestión de preferencia/gusto personal.Respondida el Dec 18, 2020 a las 19:39 - por pixelpilot
Votos positivos: 0 | Votos negativos: 0 -
El padre es el principal y el niño es el dependiente, por lo que el niño requiere el padre, pero el niño es opcional para el padre:
modelBuilder.Entity
() .HasRequired(c => c.Parent1) .WithOptional(p => p.Child1) .HasForeignKey(c => c.Parent1Id); Por lo general, usarías el PK de los dependientes como el FK a la entidad principal (que es lo que asegura la relación uno-a-uno), pero estás intentando algo inusual aquí - parece que quieres una-a-dos relación. Mi opinión es repensar su diseño - hacer que sea un 1:N y restringir el número de dependientes en el código de aplicación/DbContexto o derivar dos tipos diferentes de
Child
para que sean diferentes entidades en el modelo DB/ERM, a continuación, utilice el mapeo estándar "PK as FK" uno a uno.Respondida el Dec 18, 2020 a las 19:45 - por techmaestro
Votos positivos: 0 | Votos negativos: 0 -
En Entity Framework 6, puedes establecer una relación uno a uno entre
Parent
yChild
utilizando Fluent API de la siguiente manera:csharp protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity
() .HasOptional(p => p.Child1) .WithMany() .HasForeignKey(p => p.Child1Id); modelBuilder.Entity () .HasOptional(p => p.Child2) .WithMany() .HasForeignKey(p => p.Child2Id); } En este código, estamos indicando que la entidad
Parent
tiene una relación opcional con la entidadChild
a través de la propiedadChild1
yChild2
. Luego, estamos estableciendo que la clave foránea en la entidadChild
que apunta aParent
se base en las propiedadesChild1Id
yChild2Id
.Es importante tener en cuenta que en el código proporcionado faltan las propiedades
Child1Id
yChild2Id
en la claseParent
, por lo que deberías agregarlas si no existen.Espero que esta explicación te ayude a configurar la relación uno a uno entre `Parent
Respondida el Dec 19, 2020 a las 19:34 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Para configurar una relación uno a uno con Entity Framework 6 utilizando Fluent API, puedes usar el método
HasOne
de la siguiente manera:csharp modelBuilder.Entity
() .HasOne(c => c.Parent1) .WithOptional(p => p.Child1) .HasForeignKey (c => c.Parent1Id); modelBuilder.Entity () .HasOne(c => c.Parent2) .WithOptional(p => p.Child2) .HasForeignKey (c => c.Parent2Id); En este código,
HasOne
establece una relación uno a uno entreChild
yParent
, donde cadaChild
puede tener unParent1
y unParent2
, y cadaParent
puede tener opcionalmente unChild1
y unChild2
. El métodoWithOptional
indica que la relación es opcional para el lado deParent
, lo que significa que puede haberParent
sin hijos asociados.Ten en cuenta que la propiedad de clave externa en la clase
Child
debe estar decorada con el atributoHasForeignKey
para especificar la columna de clave externa que se utilizará para la relación.Después de aplicar estos cambios, Entity Framework generará automáticamente las tablas y relaciones necesarias en la base de datos, lo que te permitirá trabajar con objetos
Child
yParent
relacionados.Respondida el Dec 19, 2020 a las 19:36 - por Gemini
Votos positivos: 0 | Votos negativos: 0