在EF Core中添加外键列

时间:2017-12-15 01:43:05

标签: entity-framework ef-migrations ef-core-2.0

我有一个现有的表Projects,我想在其中添加UserId列,其中UserId是外键。 Projects现在有一个名单列表,但我希望每个用户都能管理自己的项目。有了"孤儿"我很好最初,因为列表足够小,我可以手动清理它们。

我已更新我的模型以包含UserId和导航属性User(可能不相关,但Entity这里是基类Id和{{1} })

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; }
}

运行update-database时会转换为此SQL

    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);
    }

失败并出现此错误

ALTER TABLE [Projects] ADD CONSTRAINT [FK_Projects_Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [Users] ([Id]) ON DELETE SET NULL;

我做错了什么?

2 个答案:

答案 0 :(得分:2)

下面这一行导致了问题,因为您希望Project上有一个可以为空的FK

builder.Property(x => x.UserId).IsRequired();

此外,您生成的迁移已经有提示:

 nullable: false,

只需删除Configure方法上的那一行即可。您可能还需要通过运行Remove-Migration然后再次运行add-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类的人来说它仍然很好。

答案 1 :(得分:0)

在功能配置中指定:

builder.Property(x => x.UserId).IsRequired();

这是不是意味着UserId可能不为空?但是你希望它为空?