EF Core OnDelete 限制添加附加列

g_b*_*g_b 5 entity-framework entity-framework-core asp.net-core

我有多对多关系的模型:

用户

public class User
{
    public int Id { get; set; }
    public int CompanyId { get; set; }

    [Required]
    [StringLength(100)]
    public string Username { get; set; }

    [Required]
    public string PasswordHash { get; set; }

    [ForeignKey("CompanyId")]
    public Company Company { get; set; }

    public ICollection<UserRole> UserRoles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

角色

public class Role
{
    public int Id { get; set; }
    public int CompanyId { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }

    [StringLength(500)]
    public string Description { get; set; }

    [ForeignKey("CompanyId")]
    public Company Company { get; set; }

    public ICollection<RolePrivilege> RolePrivileges { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

用户角色

public class UserRole
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public int RoleId { get; set; }

    [ForeignKey("UserId")]
    public User User { get; set; }

    [ForeignKey("RoleId")]
    public Role Role { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我创建迁移然后尝试更新数据库时,它引发了多个级联路径的错误。解决方案是设置“删除时不执行任何操作”,因此我在 OnModelCreating 中添加了以下内容:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<UserRole>()
            .HasIndex(e => new { e.UserId, e.RoleId })
            .IsUnique();

    modelBuilder.Entity<UserRole>()
        .HasOne(e => e.User)
        .WithMany()
        .OnDelete(DeleteBehavior.Restrict);

    modelBuilder.Entity<UserRole>().ToTable("UserRoles");
}
Run Code Online (Sandbox Code Playgroud)

现在表已创建,但我没想到的一件事是它创建了一个额外的列。生成后的迁移代码如下所示:

migrationBuilder.CreateTable(
            name: "UserRoles",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                RoleId = table.Column<int>(type: "int", nullable: false),
                UserId = table.Column<int>(type: "int", nullable: false),
                UserId1 = table.Column<int>(type: "int", nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_UserRoles", x => x.Id);
                table.ForeignKey(
                    name: "FK_UserRoles_Roles_RoleId",
                    column: x => x.RoleId,
                    principalTable: "Roles",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_UserRoles_Users_UserId",
                    column: x => x.UserId,
                    principalTable: "Users",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_UserRoles_Users_UserId1",
                    column: x => x.UserId1,
                    principalTable: "Users",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });
Run Code Online (Sandbox Code Playgroud)

如您所见,它添加了一个额外的列 UserId1。

我做错了什么或者如何防止这种情况发生?

Iva*_*oev 6

这是典型的关系流畅配置错误的结果 - 使用Has/的无参数重载With(有效地告诉 EF 没有相应的导航属性),而实际上存在导航属性。在这种情况下,EF 会将缺少的导航属性映射到另一端没有导航属性的另一个关系,并且默认按照 FK 属性/列名称约定。

要解决此问题,请确保使用代表导航属性存在/不存在的正确重载(并根据添加/删除导航属性的情况更新它们)。根据您的情况,更换

.WithMany()
Run Code Online (Sandbox Code Playgroud)

.WithMany(e => e.UserRoles)
Run Code Online (Sandbox Code Playgroud)