C# 具有自定义列名的同一表的ForeignKey

C# 具有自定义列名的同一表的ForeignKey,c#,entity-framework-core,ef-fluent-api,ef-core-2.0,C#,Entity Framework Core,Ef Fluent Api,Ef Core 2.0,我有一个型号用户: public class User { [Key] public int IDUser { get; set; } [Required] public string Forename { get; set; } [Required] public string Name { get; set; } public int? IDUser_CreatedBy { get;

我有一个型号
用户

public class User
{
    [Key]
    public int IDUser { get; set; }
    [Required]
    public string Forename { get; set; }
    [Required]
    public string Name { get; set; }                          

    public int? IDUser_CreatedBy { get; set; }
    public User User_CreatedBy { get; set; }
}
用户可以让其创建者(
User\u CreatedBy
)及其ID(
IDUser\u CreatedBy
)位于同一个表中,当然,但我希望有机会将其保留为空值(
User
,创建者未知)。这就是为什么
IDUser\u CreatedBy
具有
int?
可空类型的原因

我不知道如何设置我的fluent API,以便将同一个表中的外键
IDUser\u CreatedBy
绑定到主键
IDUser

我知道,如果我从该模型中删除
IDUser\u CreatedBy
外键并添加新的迁移,那么EF core将隐式地为我创建阴影属性外键,但我希望以后有机会更新我的
用户
(在MVC控制器中)使用自定义创建的列
IDUser\u CreatedBy
,可以自己命名该列。此外,我不想要那个shadow属性,因为我无法控制该列的命名

我怎样才能做到这一点

编辑

@IvanStoev-感谢您的回答,但您的示例没有为我生成有效的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Users_Users_CreatedByIDUser",
            table: "Users");

        migrationBuilder.RenameColumn(
            name: "CreatedByIDUser",
            table: "Users",
            newName: "UserIDUser");

        migrationBuilder.RenameIndex(
            name: "IX_Users_CreatedByIDUser",
            table: "Users",
            newName: "IX_Users_UserIDUser");

        migrationBuilder.AddColumn<int>(
            name: "IDUser_CreatedBy",
            table: "Users",
            nullable: true);

        migrationBuilder.CreateIndex(
            name: "IX_Users_IDUser_CreatedBy",
            table: "Users",
            column: "IDUser_CreatedBy");

        migrationBuilder.AddForeignKey(
            name: "FK_Users_Users_IDUser_CreatedBy",
            table: "Users",
            column: "IDUser_CreatedBy",
            principalTable: "Users",
            principalColumn: "IDUser",
            onDelete: ReferentialAction.Restrict);

        migrationBuilder.AddForeignKey(
            name: "FK_Users_Users_UserIDUser",
            table: "Users",
            column: "UserIDUser",
            principalTable: "Users",
            principalColumn: "IDUser",
            onDelete: ReferentialAction.Restrict);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Users_Users_IDUser_CreatedBy",
            table: "Users");

        migrationBuilder.DropForeignKey(
            name: "FK_Users_Users_UserIDUser",
            table: "Users");

        migrationBuilder.DropIndex(
            name: "IX_Users_IDUser_CreatedBy",
            table: "Users");

        migrationBuilder.DropColumn(
            name: "IDUser_CreatedBy",
            table: "Users");

        migrationBuilder.RenameColumn(
            name: "UserIDUser",
            table: "Users",
            newName: "CreatedByIDUser");

        migrationBuilder.RenameIndex(
            name: "IX_Users_UserIDUser",
            table: "Users",
            newName: "IX_Users_CreatedByIDUser");

        migrationBuilder.AddForeignKey(
            name: "FK_Users_Users_CreatedByIDUser",
            table: "Users",
            column: "CreatedByIDUser",
            principalTable: "Users",
            principalColumn: "IDUser",
            onDelete: ReferentialAction.Restrict);
    }
它将我的残余阴影属性ForeignKey重命名为一个新名称,但保留该阴影属性。迁移还添加了新列
IDUser\u CreatedBy
,该列不是ForeignKey(该列没有
AddForeignKey
CreateIndex
方法)

编辑3

@伊万·斯托夫——你说得对。我没有提交整个模型,因为我认为它不会对结果产生影响,但现在很明显它已经…:)首先,我确实创建了一个全新的命令行项目,并按照您所说的构建了正确的迁移。然后我意识到我的模型有另一个属性,它是
public List UsersAdded{get;set;}
,它描述了该特定
用户添加的所有用户。这就是罪魁祸首。它将新列
UserIDUser
添加到新创建的迁移中。所以最后一个问题是:如何使用新属性
public List UsersAdded{get;set;}
实现我所需要的一切?因为我想有机会将此
用户
在我的MVC控制器中获取
用户
时创建的
用户
集合包括在内。作为一种形式,我提交了我的整个模型(这次正确):

公共类用户
{
[关键]
public int IDUser{get;set;}
[必需]
公共字符串名{get;set;}
[必需]
公共字符串名称{get;set;}
公共字符串AvatarPath{get;set;}
公共字符串电子邮件{get;set;}
公共字符串PhoneNumber{get;set;}
公共字符串密码{get;set;}
公共bool IsWebUser{get;set;}
public DateTimeOffset CreatedAt{get;set;}
公共int?IDUser_由{get;set;}创建
公共用户用户_CreatedBy{get;set;}
公共列表UsersAdded{get;set;}
}

EF Core fluent API为您提供了对表列命名的完全控制,无论您使用的是显式还是阴影模型属性。非常规外键属性映射为关系配置的
HasForeignKey
fluent API

您的实体模型属于显式FK属性类别,可按如下方式映射:

modelBuilder.Entity<User>()
    .HasOne(e => e.User_CreatedBy) // reference navigation property
    .WithMany() // no collection navigation property
    .HasForeignKey(e => e.IDUser_CreatedBy); // foreign key property
modelBuilder.Entity()
.HasOne(e=>e.User_CreatedBy)//引用导航属性
.WithMany()//没有集合导航属性
.HasForeignKey(e=>e.IDUser_CreatedBy);//外键属性

添加到@Ivan answer中,您还可以在类中使用
[column(“NewColumnName”)]
属性来更改列名。

显然,您的代码中还有其他内容没有显示在此处。EF迁移无法使用此模型和建议的fluent配置创建列“UserIDUser”。用你的帖子和我的答案中的代码创建一个干净的新项目,你会看到迁移将生成一个正确的
CreateTable
public class User
{
    [Key]
    public int IDUser { get; set; }
    [Required]
    public string Forename { get; set; }
    [Required]
    public string Name { get; set; }
    public string AvatarPath { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public string Password { get; set; }
    public bool IsWebUser { get; set; }
    public DateTimeOffset CreatedAt { get; set; }

    public int? IDUser_CreatedBy { get; set; }
    public User User_CreatedBy { get; set; }

    public List<User> UsersAdded { get; set; }
}
modelBuilder.Entity<User>()
    .HasOne(e => e.User_CreatedBy) // reference navigation property
    .WithMany() // no collection navigation property
    .HasForeignKey(e => e.IDUser_CreatedBy); // foreign key property