我有一个现有的表 Projects
我想添加一个 UserId
列到,哪里UserId
是外键。 Projects
现在有一个名字列表,但我希望每个用户都管理自己的项目。我最初可以接受“孤儿”,因为列表足够小,我可以手动清理它们。
我已更新我的模型以包含 UserId
和导航属性 User
(可能不相关,但 Entity
这里是带有 Id
和 DateModified
的基类)
public class Project : Entity
{
public string Name { get; set; }
public Guid? UserId { get; set; } //tried this as nullable and non nullable
public User User { get; set; }
}
我的相关映射文件是
public class ProjectMap : IEntityTypeConfiguration<Project>
{
public void Configure(EntityTypeBuilder<Project> builder)
{
builder.Property(x => x.Name).IsRequired();
builder.Property(x => x.UserId).IsRequired();
builder.HasOne(x => x.User)
.WithMany(x => x.Projects)
.HasForeignKey(x => x.UserId)
.OnDelete(DeleteBehavior.SetNull); //I have tried numerous combinations of things here....
}
}
我还在
User
中添加了一个导航属性。项目的实体,但未对映射类进行任何更改。public class User : Entity
{
public string EmailAddress { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Task> Tasks { get; set; }
public List<Project> Projects { get; set; }
}
由此产生的迁移:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "UserId",
table: "Projects",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateIndex(
name: "IX_Projects_UserId",
table: "Projects",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_Projects_Users_UserId",
table: "Projects",
column: "UserId",
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
}
运行更新数据库时转换为此 SQL
ALTER TABLE [Projects] ADD CONSTRAINT [FK_Projects_Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [Users] ([Id]) ON DELETE SET NULL;
并因此错误而失败
Cannot create the foreign key "FK_Projects_Users_UserId" with the SET NULL referential action, because one or more referencing columns are not nullable.
我究竟做错了什么?
最佳答案
下面的行导致了问题,因为您希望在 Project
上有一个可为空的 FK。
builder.Property(x => x.UserId).IsRequired();
此外,您生成的迁移已经有了提示:
nullable: false,
只需删除
Configure
上的那一行方法,它应该工作。您可能还需要通过运行 Remove-Migration
来删除迁移。然后再次运行添加迁移。这次你应该有这个:protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Projects",
nullable: false,
oldClrType: typeof(string),
oldNullable: true);
migrationBuilder.AddColumn<Guid>(
name: "UserId",
table: "Projects",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_Projects_UserId",
table: "Projects",
column: "UserId");
migrationBuilder.AddForeignKey(
name: "FK_Projects_Users_UserId",
table: "Projects",
column: "UserId",
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
}
如果需要,您可以通过显式设置
IsRequired
来更加具体。在配置您的关系时:private static void ConfigureProject(EntityTypeBuilder<Project> b)
{
b.Property(x => x.Name).IsRequired();
b.HasOne(x => x.User)
.WithMany(x => x.Projects)
.HasForeignKey(x => x.UserId)
.IsRequired(false)
.OnDelete(DeleteBehavior.SetNull);
}
我喜欢这样,即使该属性已经可以为空并且 EF 将使用其约定来正确创建它,但对于阅读配置并了解它的人来说仍然很好,而不必转到实际的 Project 类。
关于entity-framework - 在 EF Core 中添加外键列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47824667/