我有一个现有的表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;
我做错了什么?
答案 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可能不为空?但是你希望它为空?