Qué significa el fin principal de una asociación en la relación 1:1 en Entity framework


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 tratando de hacer esto en Entity Framework cuando recibí el error:

No se puede determinar el final principal de una asociación entre los tipos "Aplicación de consolación5.Boo ' y ' ConsoleApplication5.Foo'. El final principal de esta asociación debe configurarse explícitamente utilizando relación fluida API o anotaciones de datos.

He visto preguntas sobre StackOverflow con una solución para este error, pero quiero entender lo que el término "fin principal" significa.

Author: Luke Sampson, 2011-06-30

3 answers

En una relación uno a uno, un extremo debe ser principal y el segundo extremo debe ser dependiente. El fin principal es el que se insertará primero y que puede existir sin el dependiente. Fin dependiente es el que debe insertarse después del principal porque tiene clave foránea al principal.

En el caso de entity framework FK en dependiente también debe ser su PK por lo que en su caso debe utilizar:

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);
 351
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-30 09:00:37

También puede utilizar 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.

 166
Author: Leniel Maccaferri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-21 02:13:51

Esto es en referencia a la respuesta de @Ladislav Mrnka sobre el uso de fluent api para configurar la relación uno a uno.

Tuvo 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, tuvimos 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;
}

Aquí es cómo especificar una relación uno-a-uno usando fluent api:

modelBuilder.Entity<Bar>()
            .HasOptional(p => p.PrimaryBarOfFoo)
            .WithOptionalPrincipal(o => o.PrimaryBar)
            .Map(x => x.MapKey("PrimaryBarId"));

Tenga en cuenta que al agregar PrimaryBarId debe eliminarse, ya que lo especificamos a través de fluent api.

También tenga en cuenta que el nombre del método [WithOptionalPrincipal()][1] es algo irónico. En este caso, Principal es Bar. WithOptionalDependent() la descripción en msdn lo deja más claro.

 5
Author: Sudarshan_SMD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 15:43:20