Entity Framework Core中的一对一关系

时间:2019-03-17 08:07:52

标签: c# entity-framework entity-framework-core

过去两周来,我一直在使用.NET Core,并决定尝试EF Core(来自带有NHibernate的ASP.NET MVC)。经过一番挖掘,我发现了一个不错的扩展名为EF Visual Designer。它使我可以直观地创建模型并生成代码。

我已经定义了一个简单的一对一关系,如图所示: Simple one-to-one relationship

生成代码后,我将获得以下内容作为Fluent API代码:

modelBuilder.Entity<Authentication>()
   .ToTable("Authentications")
   .HasKey(t => t.Id);

modelBuilder.Entity<Authentication>()
    .Property(t => t.Id)
    .IsRequired()
    .ValueGeneratedOnAdd();

modelBuilder.Entity<User>()
     .ToTable("Users")
     .HasKey(t => t.Id);

modelBuilder.Entity<User>()
     .Property(t => t.Id)
     .IsRequired()
     .ValueGeneratedOnAdd();

modelBuilder.Entity<User>()
    .HasOne(x => x.Authentication)
    .WithOne()
    .HasForeignKey("Authentication_Id")
    .IsRequired();

用户类具有以下(相关)属性:

[Key]
[Required]
public Guid Id { get; set; }
...
public virtual Authentication Authentication { get; set; }

身份验证具有以下(相关)属性:

[Key]
[Required]
public Guid Id { get; set; }

但是,当我尝试生成迁移时,出现以下错误:

  

您正在配置“用户”和“身份验证”之间的关系   但在上指定了外键   “ Authentication_Id”。外键   必须在关系的一部分类型上进行定义。

我尝试切换到多对一关系,并且这种关系没有任何问题。这可能是一种解决方法,但不是很干净。这可能是由于命名问题引起的,例如两个实体都以“ Id”作为主键?

如果是这样,什么是“最佳实践”?我是否给每个实体一个唯一的ID列名称?我该如何处理具有继承了ID列的派生类的抽象实体?

2 个答案:

答案 0 :(得分:0)

您需要将外键放在另一个类上。看来您在Authentication类上没有属性“ Authentication_Id”。

答案 1 :(得分:0)

我从未使用过EF Visual Designer来生成代码,而只是通过查看您的代码,User实体需要使用Authentication的外键,或者Authentication实体需要使用外键User的键。

假设您要将外键放入User

public class User
{
    [Key]
    [Required]
    public Guid Id { get; set; }

    public Guid AuthenticationId { get; set; }

    // Even this navigation property is optional
    // for configuring one-to-one relationship
    public virtual Authentication Authentication { get; set; }
}

public Authentication
{
    [Key]
    [Required]
    public Guid Id { get; set; }
}

然后将一对一关系配置为:

modelBuilder.Entity<User>()
    .HasOne(x => x.Authentication)

    // Or like this if you don't have Authentication navigation property:
    //.HasOne<Authentication>()

    .WithOne()
    .HasForeignKey(x => x.AuthenticationId);

不,您不必为每个实体赋予唯一的ID列名称。实际上,您可以在代码中调用任何内容,然后在配置中将其重命名:

modelBuilder.Entity<User>()
    .Property(x => x.Id).HasColumnName("WHATEVER_YOU_WANT_TO_CALL_IN_DB");