具有不同列名的 EF Core 5 HasForeignKey 问题
Posted
技术标签:
【中文标题】具有不同列名的 EF Core 5 HasForeignKey 问题【英文标题】:EF Core 5 HasForeignKey Problem with Differing Column Name 【发布时间】: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 引用两个方向(父到子和子到父)的关系。
【问题讨论】:
【参考方案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 => new ForeignKeyName = table.Column<int>(type: "int", nullable: false), ParentId = table.Column<int>(type: "int", nullable: true) // this shouldn't exist ,
以上是关于具有不同列名的 EF Core 5 HasForeignKey 问题的主要内容,如果未能解决你的问题,请参考以下文章