Связь «один к одному» определяется между двумя объектами двумя разными способами, но работает только тот, который использует общие методы. Конфигурации выполняются на объекте DomainVerification
.
Учитывая 2 модели:
public class Domain
{
public long Id { get; set; }
}
public class DomainVerification
{
public long Id { get; set; }
public Domain Domain { get; set; }
}
Одна конфигурация использует общие методы, а другая — свойство навигации Domain
для настройки внешнего ключа.
// This works
public void Configure(EntityTypeBuilder<DomainVerification> builder)
{
builder.HasKey(d => d.Id);
builder.HasOne<Domain>()
.WithOne()
.HasForeignKey<Domain>("DomainId");
}
// Produces error
public void Configure(EntityTypeBuilder<DomainVerification> builder)
{
builder.HasKey(d => d.Id);
builder.HasOne(d => d.Domain)
.WithOne()
.HasForeignKey("DomainId");
}
Попытка создать миграцию с помощью второго подхода приводит к следующей ошибке:
Невозможно создать «DbContext» типа «». Исключение «Вы настраиваете связь между «DomainVerification» и «Domain», но указали внешний ключ для «DomainId». Внешний ключ должно быть определено для типа, который является частью отношения». был выброшен при попытке создать экземпляр.
Любопытно: если WithOne()
изменить на WithMany()
во втором синтаксисе, EF Core сможет сгенерировать миграцию. До сих пор я не встречал связи one-to-one
, и все конфигурации сущностей используют второй синтаксис (в отношениях «один ко многим»).
Почему второй синтаксис выдает ошибку миграции? У него есть свойство навигации Domain
, определенное в модели, поэтому оно видно даже в LINQ.
Причина, по которой это не работает для отношений «один-к-одному», заключается в том, что EF не знает, какая сущность является основной, а какая — зависимой, поэтому вам нужно использовать либо общий:
HasForeignKey<Domain>("DomainId")
или неуниверсальный:
HasForeignKey("Domain", "DomainId")
(Это работает так: для отношения «один ко многим» WithMany()
возвращает a ReferenceCollectionBuilder<TRelatedEntity,TEntity>
, который имеет метод HasForeignKey(String[])
, позволяющий просто указать столбцы. Однако WithOne()
возвращает a ReferenceReferenceBuilder<TEntity,TRelatedEntity>
, который имеет только HasForeignKey
методы, требующие указанную сущность.)