Как я уже сказал, если я закомментировал Id, все работает хорошо, но мне не нужен PK для UserDetails
Если я правильно понимаю, вы просто не хотите добавлять дополнительный столбец (например, Id
или UserDetailsId
), установленный в качестве PK. Таблица UserDetails
, которую вы хотите создать, будет иметь UserId
, которая ссылается на таблицу User
, а UserId
будет одновременно выполнять роль PK и FK.
На самом деле нет необходимости иметь свойство Id
для объекта UserDetails
. Так почему ваш код не работает? Причина в том, что вы смешали зависимую сущность и основную сущность.
Прототип HasForeignKey<>()
метода :
public virtual ReferenceReferenceBuilder<TEntity,TRelatedEntity> HasForeignKey<TDependentEntity>
(
Expression<Func<TDependentEntity,object>> foreignKeyExpression
)
where TDependentEntity : class;
Обратите внимание, что общий параметр HasForeignKey<TDependentEntity>()
представляет зависимую сущность.
А вот ваш код:
builder.Entity<User>(entity =>
{
entity.HasOne(d => d.UserDetail)
.WithOne(p => p.User)
.HasForeignKey<UserDetails>(x => x.UserId);
});
Видите это? В вашем коде entity
здесь - User
, который является основным объектом, а не зависимым объектом. Чтобы исправить это, измените свой код, как показано ниже:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<User>(entity =>
{
entity.HasOne(u => u.UserDetail).WithOne(d => d.User);
});
builder.Entity<UserDetails>(entity =>
{
// set the UserId as key
entity.HasKey(d=>d.UserId);
// the relationship between `UserDetails : User` is 1-to-1
entity.HasOne(d=>d.User).WithOne(u=>u.UserDetail)
// set column `UserId` as the FK for the dependent entity , i.e. , the `UserDetails` .
.HasForeignKey<UserDetails>(u=>u.UserId);
});
}
Будет сгенерирована таблица UserDetails
с столбцом UserId
, установленным как PrimaryKey и ForeignKey одновременно:
CREATE TABLE [dbo].[UserDetails] (
[Biography] NVARCHAR (MAX) NULL,
[Country] NVARCHAR (MAX) NULL,
[FacebookLink] NVARCHAR (MAX) NULL,
[TwitterLink] NVARCHAR (MAX) NULL,
[SkypeLink] NVARCHAR (MAX) NULL,
[UserId] NVARCHAR (450) NOT NULL,
CONSTRAINT [PK_UserDetails] PRIMARY KEY CLUSTERED ([UserId] ASC),
CONSTRAINT [FK_UserDetails_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
Кстати, в SQL Server Object Explorer Visual Studio, похоже, есть ошибка (см. мой вопрос здесь ), приводящая к ошибке, что мы не можем видеть уже существующие противоречия FK.
Однако мы можем доказать это, попытавшись вставить строку с несуществующим UserId:
insert into UserDetails
(Biography,UserId)
values
('hello,wrold','here-is-a-non-existing-user-id')
Будет выдано следующее сообщение, как и ожидалось:
Сообщение 547, Уровень 16, Состояние 0, Строка 1
Оператор INSERT конфликтовал с ограничением FOREIGN KEY "FK_UserDetail_AspNetUsers_UserId". Конфликт произошел в базе данных «App-EFCore-FK-Test», таблице «dbo.AspNetUsers», столбце «Id».
Оператор был расторгнут.