简体   繁体   中英

.NET Core creating non-nullable FK constraint with IdentityUser

I am trying to create a relationship from my main IdentityUser to another class, using the EF migrations in .NET Core 2.2. There is an issue I am running into, and that is the migrations are being created with a null FK constraint. This is something I do not want.

I fear, that I should not be manually editing the migration file (to fix this issue), as when I change these models in the future, my manual edit will be overwritten (because my classes are somehow coded incorrectly).

These are the classes I have..

public class ApplicationUser : IdentityUser
{
    public List<Purchase> Purchases { get; set; }
}

public class Purchase
{
    public int Id { get; set; }
    // others
}

The resulting migration file has a nullable: true property set on ApplicationUserId

migrationBuilder.CreateTable(
            name: "Purchase",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                ApplicationUserId = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Purchase", x => x.Id);
                table.ForeignKey(
                    name: "FK_Purchase_AspNetUsers_ApplicationUserId",
                    column: x => x.ApplicationUserId,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

Not correct. So, I add properties in the Purchase class (like I have in other POCOs in my project)..

public class Purchase
{
    public int Id { get; set; }
    // others

    public int ApplicationUserId { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
}    

and re-run the migration regeneration..

migrationBuilder.CreateTable(
            name: "Purchase",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
                ApplicationUserId = table.Column<int>(nullable: false),
                ApplicationUserId1 = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Purchase", x => x.Id);
                table.ForeignKey(
                    name: "FK_Purchase_AspNetUsers_ApplicationUserId1",
                    column: x => x.ApplicationUserId1,
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

I now get the proper non-nullable constraint, but it is a duplicate. (There is a 1 tacked on). My questions are:

  1. Is it safe for me to simply modify the migration file and call it a day?
  2. How can I create a relationship between my ApplicationUser and Purchase classes so the migration file that is generated gives me a non-nullable FK constraint?

1) You can, but each consequent migration will remake this field an d cause you to have an issue. Also since the data type does not match it will not work as expected

2) The id type of the foreign key is wrong. Application user has a primary key of type string but you are using int so it is failing to recognize the correct foreign key.

After you correct that, put the Required attribute on the class. So the final class would look like

using System.ComponentModel.DataAnnotations;

public class Purchase
{
    public int Id { get; set; }
    // others

    [Required]
    public string ApplicationUserId { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
} 

You can generate the migration script using the Add-Migration command, after that you can edit the migration source code and add at least 1 record right after the creation of the new table using:

migrationBuilder.InsertData(
    table: "Organizations",
    columns: new[] { "OrganizationName", "IsDeleted" },
    values: new object[,]
    {
        { "Test organization", false }
    });

After that you should be able to manage the creation of the new foreign key field, giving 1 as default value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM