1

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?

2
  • Where are you putting that code? In the OnModelCreating() override of the ApplicationUserDbContext class? Commented May 11, 2016 at 17:57
  • That's on the initial migration file. Commented May 11, 2016 at 18:05

1 Answer 1

1

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(); 
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for sharing how you added new attributes. I aggree with you on the subject of not altering the key structure, it's going to be a pain changing the foreign keys on other tables. I think I'll just append the TenantId before the UserId, that way I won't have repeated users on the table.
You're welcome. Ok, sounds like a plan. How about an up vote? I gave you one. Maybe even mark it as the accepted answer if you agree that changing the primary keys is probably not a good idea.
Thanks. You could add the TenantId field and add a unique key constraint in the MyDbContext class. It should probably work there. I have one where I added a few new tables and added fields related to those tables in the Identity tables. Then created foreign key constraints to my new tables.
I think that won't work. Since the UserId is the table key, it won't be possible to have two records of the same user for different tenants. That was what I was trying to do.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.