Что означает основной конец ассоциации в соотношении 1:1 в структуре Entity

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

Я пытался сделать это в Entity Framework, когда получил ошибку:

Невозможно определить главный конец связи между типами 'ConsoleApplication5.Boo' и 'ConsoleApplication5.Foo'. Основной конец этой ассоциации должен быть явно сконфигурирован с использованием либо свободно распространяемые API или аннотации данных.

Я видел вопросы о StackOverflow с решением для этой ошибки, но я хочу понять, что означает термин "главный конец".

Ответ 1

В отношениях "один к одному" один конец должен быть основным, а второй конец должен быть зависимым. Основной конец - тот, который будет вставлен первым и который может существовать без зависимого. Зависимый конец - тот, который должен быть вставлен после принципала, потому что у него есть внешний ключ для принципала.

В случае сущности фрейма FK в зависимом случае также должен быть PK, поэтому в вашем случае вы должны использовать:

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

Или плавное отображение

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);

Ответ 2

Вы также можете использовать атрибут аннотации данных [Required], чтобы решить эту проблему:

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 требуется для Boo.

Ответ 3

Это со ссылкой на @Ladislav Mrnka ответ на использование свободного api для настройки отношения "один к одному".

Если бы ситуация FK of dependent must be it PK была невозможной.

например: Foo уже имеет отношения "один ко многим" с 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;
}

Теперь нам пришлось добавить еще одну взаимную связь между Foo и Bar а именно

public class Foo{
   public Guid FooId;
   pubic 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;
}

Вот как указать отношения "один-к-одному", используя беглый api:

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

Обратите внимание, что при добавлении PrimaryBarId необходимо удалить, поскольку мы укажем его через беглый api.

Также обратите внимание, что имя метода [WithOptionalPrincipal()][1] является своеобразным ироничным. В этом случае Principal Bar. Описание WithOptionalDependent() в msdn делает его более понятным.