¿Qué significa el fin principal de una asociación en una relación 1:1 en el marco de la entidad?
public class Foo
{
public string FooId{get;set;}
public Boo Boo{get;set;}
}
public class Boo
{
public string BooId{get;set;}
public Foo Foo{get;set;}
}
Estaba intentando hacer esto en Entity Framework cuando recibí el error:
No se puede determinar el final principal de una asociación entre los tipos 'ConsoleApplication5.Boo' y 'ConsoleApplication5.Foo'. El extremo principal de esta asociación debe configurarse explícitamente mediante la API fluida de relación o anotaciones de datos.
He visto preguntas en StackOverflow con una solución para este error, pero quiero entender qué significa el término "extremo principal".
En una relación uno a uno, un extremo debe ser principal y el segundo extremo debe ser dependiente. El extremo principal es el que se insertará primero y que puede existir sin el dependiente. El extremo dependiente es el que debe insertarse después del principal porque tiene una clave externa para el principal.
En el caso de la FK del marco de la entidad, el dependiente también debe ser su PK, por lo que en su caso debe usar:
public class Boo
{
[Key, ForeignKey("Foo")]
public string BooId{get;set;}
public Foo Foo{get;set;}
}
O mapeo fluido
modelBuilder.Entity<Foo>()
.HasOptional(f => f.Boo)
.WithRequired(s => s.Foo);
También puedes usar el [Required]
atributo de anotación de datos para resolver esto:
public class Foo
{
public string FooId { get; set; }
public Boo Boo { get; set; }
}
public class Boo
{
public string BooId { get; set; }
[Required]
public Foo Foo {get; set; }
}
Foo
se requiere para Boo
.
Esto es en referencia a la respuesta de @Ladislav Mrnka sobre el uso de una API fluida para configurar una relación uno a uno.
Tenía una situación en la que tener FK of dependent must be it's PK
no era factible.
Por ejemplo, Foo
ya tiene una relación de uno a muchos con Bar
.
public class Foo {
public Guid FooId;
public virtual ICollection<> Bars;
}
public class Bar {
//PK
public Guid BarId;
//FK to Foo
public Guid FooId;
public virtual Foo Foo;
}
Ahora teníamos que agregar otra relación uno a uno entre Foo y Bar.
public class Foo {
public Guid FooId;
public Guid PrimaryBarId;// needs to be removed(from entity),as we specify it in fluent api
public virtual Bar PrimaryBar;
public virtual ICollection<> Bars;
}
public class Bar {
public Guid BarId;
public Guid FooId;
public virtual Foo PrimaryBarOfFoo;
public virtual Foo Foo;
}
A continuación se explica cómo especificar una relación uno a uno utilizando una API fluida:
modelBuilder.Entity<Bar>()
.HasOptional(p => p.PrimaryBarOfFoo)
.WithOptionalPrincipal(o => o.PrimaryBar)
.Map(x => x.MapKey("PrimaryBarId"));
Tenga en cuenta que, si bien PrimaryBarId
es necesario eliminar la adición, ya que lo especificamos a través de la API fluida.
También tenga en cuenta que el nombre del método [WithOptionalPrincipal()][1]
es algo irónico. En este caso, Principal es Bar. La descripción WithOptionalDependent() en msdn lo hace más claro.