创建 1:n 关系时,Entity Framework Code First 在数据库中生成两个外键列

Posted

技术标签:

【中文标题】创建 1:n 关系时,Entity Framework Code First 在数据库中生成两个外键列【英文标题】:Entity Framework Code First generates two foreign key columns in database when creating a 1:n relationship 【发布时间】:2017-07-21 09:58:27 【问题描述】:

我想使用实体框架创建一个 1:n 关系,基于用于创建关系的命名约定。我正在使用代码优先。 Entity Framework 忽略了约定并且总是创建两个外键列,而不是只有一个:

StreamWorkerUser_Id(我只想要这个专栏) StreamWorkerUser_Id1

配置类配置如下:

AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;

我正在使用 Microsoft.Identity 框架,为所有模型提供自定义类。

我的 DbContext 类如下所示。

public class StreamWorkerDataContext : IdentityDbContext<StreamWorkerUser, StreamWorkerRole, int, StreamWorkerUserLogin, StreamWorkerUserRole, StreamWorkerUserClaim>

    public DbSet<Task> Tasks  get; set; 

Task 模型:

public class Task : StreamWorkerEntity

    public StreamWorkerUser StreamWorkerUser  get; set; 

StreamWorkerUser 模型:

public class StreamWorkerUser : IdentityUser<int, StreamWorkerUserLogin, StreamWorkerUserRole, StreamWorkerUserClaim>
    
        public virtual List<Task> Tasks  get; set;  // also tested ICollection
    

Task 类继承自这个基类型,这里也定义了StreamWorkerUser 类型的两个属性(但是这些列在数据库中正确生成。):

public class StreamWorkerEntity

    [Key]
    public int Id  get; set; 
    public DateTimeOffset Created  get; set; 
    public DateTimeOffset Updated  get; set; 
    public StreamWorkerUser Creator  get; set; 
    public StreamWorkerUser LastEditor  get; set; 

有没有可能是CreatorLastEditor属性干扰了数据库迁移?

我是否正确理解了约定?

更多信息:

实体框架版本 6.1.3 Microsoft.AspNet.Identity.Core 2.2.1 Microsoft.AspNet.Identity.EntityFramework 2.2.1 ASP.NET 4 MVC 5 Azure 云中的 SQL Server C# 6.0 .NET Framework 4.5.2 所有这些代码都在类库中

【问题讨论】:

如果您只需要一个外键,您希望如何存储与 Creator 和 LastEditor 的关系? @faint220 我不想要一个外键。应该有三个。一种用于Creator,一种用于LastEditor,另一种用于StreamWorkerUser。目前生成了 4 列:Creator_Id、LastEditor_Id、StreamWorkerUser_Id、StreamWorkerUser_Id1。 你试过实体类型配置吗???您可以使用 fluent api 显式声明外键 我遇到了问题。你的任务有一个 StreamWorkerUser,它也继承自 StreamWorkerEntity,它有另一个 StreamWorkerUser 类型的字段。总而言之,StreamWorkerUser 有很多任务,而任务有 2 个用户(从数据库的角度来看,这算作很多)。您的关系似乎是多:多而不是 1:多。命名约定不关心关系逻辑的正确性。重新分析你的类和关系的概念。 看看我在这里发布的答案:***.com/questions/59465609/… 【参考方案1】:

所以你可能会认为 EF 在这种情况下:

 public StreamWorkerUser Creator  get; set; 
 public StreamWorkerUser LastEditor  get; set; 

将创建 creator_id 和 lasteditor_id,但它不会,因为 EF 使用了类名并创建了 StreamWorkerUser_Id 和 StreamWorkerUser_Id1,因为已经使用了 StreamWorkerUser_Id。默认情况下,如果按类(而不是 int 字段)建立关系,EF 根据类名(而不是字段名)生成其列名。

如果您想为这些 FK 指定列名,您可以这样做:

    public int CreatorId  get; set;  //this field name will be column name
    [ForeignKey("StreamWorkerUser")]
    public StreamWorkerUser Creator  get; set; 

    public int EditorId  get; set;  //this field name will also be column name
    [ForeignKey("StreamWorkerUser")]
    public StreamWorkerUser Editor  get; set; 

【讨论】:

感谢您的回答,但在我的情况下,列名是从字段名生成的。请参阅问题下的评论。

以上是关于创建 1:n 关系时,Entity Framework Code First 在数据库中生成两个外键列的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 和 .NET 的一对一关系

八StarUML的Entity-Relationship Diagram(实体关系图)示例

Entity Framework Code First 从两个表和一对多关系创建类

核心数据关系创建

Entity Framework Core 实体关系的配置

Entity Framework 4.1 - 非键列之间的关系