【问题标题】:EF Core 5 HasForeignKey Problem with Differing Column Name具有不同列名的 EF Core 5 HasForeignKey 问题
【发布时间】:2021-10-10 20:48:11
【问题描述】:

环境:.Net 5.0、EntityFrameworkCore 5.0、MS Sql Server

我已经在我的数据库中设置了一对多关系(使用HasForeignKey),但是当我尝试使用.Include(x => x.Parent) 从子级访问父记录时,我得到一个无效的列名错误。我过去做过很多次这种类型的事情,但总是Child 表有一个名为ParentTableName + Id 的属性(以及所述属性上的FK)。在这种失败的情况下,属性与该模式不匹配。

所以我的问题是:为什么 EF 会忽略我的 Fluent API 配置?在我看来,如果我正确设置了关系(并且每列上的数据类型匹配),那么该列被称为什么并不重要。在流畅的 api 设置中我需要采取一些额外的步骤吗?请参见下面的示例:

public class Parent
{
    public int Id { get; set; }
    public IEnumerable<Child> Children { get; set; }
}

public class Child 
{
    public int Id { get; set; }
    public int ForeignKeyName { get; set; } // This could say anything, just not "ParentId"
    
    [NotMapped] // Included so add-migration doesn't try to create a mapping, but when removed I get the same error
    public Parent Parent { get; set; }
}

还有我的配置

modelBuilder.Entity<Parent>(entity =>
{
    entity.HasMany<Child>()
    .WithOne(x => x.Parent)
    .HasForeignKey(x => x.ForeignKeyName);
});

失败的用法:

var children = _context.Children.Include(x => x.Parent).ToList(); // Says "Invalid Column Name 'ParentId'"

外键已在数据库中设置,但当我尝试运行 add-migration 时,它仍然建议创建 a) 在 Child 上创建一个名为 ParentId 的新列(为什么?),b) 在所述列,以及 c) 使用ParentId 的外键。我宁愿了解这里发生了什么,也不愿只是更改属性名称并保持幸福的无知。

编辑 由于评论线程很长,因此更新以明确答案。关键是要确保 [NotMapped] 在两个导航属性上,并且(在下面的回答中)让流式 API 引用两个方向(父到子和子到父)的关系。

【问题讨论】:

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


    【解决方案1】:

    此代码在 VS 2019 中测试,成功创建 ForeignKeyName ForeignKey 的数据库。

    你必须修复类

    public class Parent
    {
       [Key]
        public int Id { get; set; }
        [InverseProperty(nameof(Child.Parent))]
        public IEnumerable<Child> Children { get; set; }
    }
    
    public class Child 
    {
        [Key]
        public int Id { get; set; }
    
        public int ForeignKeyName { get; set; } 
    
        [ForeignKey(nameof(ForeignKeyName))]
        [InverseProperty("Children")]
        public Parent Parent { get; set; }
    }
    

    或数据库上下文

              modelBuilder.Entity<Child>(entity =>
                {
                    entity.HasOne(d => d.Parent)
                       .WithMany(p => p.Children)
                       .HasForeignKey(d => d.ForeignKeyName);
                });
    

    您必须删除以前的 Migrations 文件夹并删除以前的数据库。在此之后使用 Add-Migration InitialCreate 进行清晰的迁移。然后使用更新数据库。

    【讨论】:

    • 这些对我不起作用。第一个代码块中的更改没有任何效果(Include 调用上的错误消息相同);添加第二个更改(我之前尝试过并希望修复它)会导致错误“无效的列名 ParentId1”;请注意名称中的 1,EF 有时会尝试添加阴影属性。当它被告知要使用什么属性作为键时,不知道为什么它想要一个影子属性。
    • @broccoli_rob 您必须删除所有旧数据库迁移文件夹和旧数据库。在此之后进行新的迁移,这将在尝试进行新查询之前创建一个新的数据库
    • 似乎是一个核选项,但即使这样做,新的迁移文件也有这一行:migrationBuilder.RenameColumn(name: "ForeignKeyName", table: "Child", newName: ParentId1");,并且当第一次构建表时,它会尝试创建列“ParentId1” ,表示同样的问题。
    • @broccoli_rob 我刚刚在 VS 2019 中测试了我的代码。成功创建了带有 ForeignKeyName ForeignKey 的数据库。
    • 是的,我得到了正确的 FK,但也得到了新列 ParentId,以及该属性上的 FK,这似乎是 EF 在运行 Include 时想要使用的。请问您使用的是哪个版本的 EF Core? migrationBuilder.CreateTable(name: "Child", columns: table =&gt; new { ForeignKeyName = table.Column&lt;int&gt;(type: "int", nullable: false), ParentId = table.Column&lt;int&gt;(type: "int", nullable: true) // this shouldn't exist },
    猜你喜欢
    • 2021-07-27
    • 2021-06-04
    • 2021-06-04
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2020-11-27
    相关资源
    最近更新 更多