Entity Framework Core 中的一对一关系

Roe*_*oel 5 c# entity-framework entity-framework-core

过去几周我一直在研究 .NET Core,并决定尝试 EF Core(来自 ASP.NET MVC 和 NHibernate)。经过一番挖掘后,我发现了一个很好的扩展,称为EF Visual Designer。它允许我直观地创建模型并生成代码。

我定义了一个简单的一对一关系,如图所示: 简单的一对一关系

生成代码后,我得到以下 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();
Run Code Online (Sandbox Code Playgroud)

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

public Class User {
    [Key]
    [Required]
    public Guid Id { get; set; }
    ...
    public virtual Authentication Authentication { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Authentication  {
    [Key]
    [Required]
    public Guid Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Dav*_*ang 7

我从未使用 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 class Authentication
{
    [Key]
    [Required]
    public Guid Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

那么一对一关系应配置为:

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);
Run Code Online (Sandbox Code Playgroud)

不,您不必为每个实体提供唯一的 ID 列名称。事实上,您可以调用代码中的任何内容并在配置中重命名它:

modelBuilder.Entity<User>()
    .Property(x => x.Id).HasColumnName("WHATEVER_YOU_WANT_TO_CALL_IN_DB");
Run Code Online (Sandbox Code Playgroud)

  • 尝试在 ```.HasForeignKey(x =&gt; x.AuthenticationId);``` 上构建时出现错误;``` 但 ```.HasForeignKey&lt;User&gt;(x =&gt; x.AuthenticationId);``` 对我有用 (5认同)