简体   繁体   中英

Entity Framework 7 composite keys in migrations

I'm trying MVC 6, Entity Framework 7 and ASP.NET Identity for the first time. I just generated a default project and I'm changing the login process to support accounts by tenant, based on the following tutorial.

https://www.scottbrady91.com/ASPNET-Identity/Quick-and-Easy-ASPNET-Identity-Multitenancy

The thing is, when I try to change the initial migration to support a composite key (Id,TenentId) on the AspNetUsers table it simply fails with a generic message. The migration code is the following.

migrationBuilder.CreateTable(
                name: "AspNetUsers",
                columns: table => new
                {
                    Id = table.Column<string>(nullable: false),
                    TenantId = table.Column<string>(nullable: false),
                    AccessFailedCount = table.Column<int>(nullable: false),
                    ConcurrencyStamp = table.Column<string>(nullable: true),
                    Email = table.Column<string>(nullable: true),
                    EmailConfirmed = table.Column<bool>(nullable: false),
                    LockoutEnabled = table.Column<bool>(nullable: false),
                    LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
                    NormalizedEmail = table.Column<string>(nullable: true),
                    NormalizedUserName = table.Column<string>(nullable: true),
                    PasswordHash = table.Column<string>(nullable: true),
                    PhoneNumber = table.Column<string>(nullable: true),
                    PhoneNumberConfirmed = table.Column<bool>(nullable: false),
                    SecurityStamp = table.Column<string>(nullable: true),
                    TwoFactorEnabled = table.Column<bool>(nullable: false),
                    UserName = table.Column<string>(nullable: true)                    
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_ApplicationUser", x => new { x.Id, x.TenantId });
                });

I also tried the following code but it also doesn't work.

constraints: table =>
                    {
                        table.PrimaryKey("PK_ApplicationUser", x => x.Id);     
                        table.PrimaryKey("PK_ApplicationUser", x => x.TenantId);    
                    });

If I leave it as a non composite key the migration executes successfully.

constraints: table =>
                {
                    table.PrimaryKey("PK_ApplicationUser", x => x.Id);
                });

I tried to define a unique constraint over both columns but I wasn't able to find a way to do it.

Does anyone have any thoughts on this?

Any customization of the Identity tables needs to be done by creating derived classes of the Identity model classes and/or by creating a derived class from the IdentityDbContext class.

But I wouldn't try changing the primary key structure of the Identity tables. I seriously doubt that will work and if it does, there's no gaurantee that it will work properly.

Just to get you pointed in the right direction, here's how I modified my IdentityUser class (AspNetUsers table). I added a few properties to store data I retrieve from Active Directory.

public class ApplicationUser : IdentityUser
{
    [Required]
    [StringLength(50)]
    public string FirstName { get; set; }

    [Required]
    [StringLength(50)]
    public string LastName { get; set; }

    [Required]
    public bool Active { get; set; }
}

Doing this requires that you create a derived class from the IdentityDbContext class that uses the model class above. In mine I rename the Identity tables.

public class MyDbContext : IdentityDbContext<ApplicationUser>
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        //Rename the ASP.NET Identity tables.
        builder.Entity<ApplicationUser>().ToTable("User");
        builder.Entity<IdentityRole>().ToTable("Role");
        builder.Entity<ApplicationRole>().ToTable("Role");
        builder.Entity<IdentityUserRole<string>>().ToTable("UserRole");
        builder.Entity<IdentityUserLogin<string>>().ToTable("UserLogin");
        builder.Entity<IdentityUserClaim<string>>().ToTable("UserClaim");
        builder.Entity<IdentityRoleClaim<string>>().ToTable("UserRoleClaim");
    }
}

Then in the ConfigureServices() method in Startup.cs

//Add Identity services.
services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<MyDbContext>()  
    .AddDefaultTokenProviders();

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