I am attempting to incorporate ASP.NET Identity into a new application that currently uses a SQL script to create the database schema. As we will need to create Foreign Key
So the new 1.1-alpha1 bits will have something close to the following by default. This might be what you are looking for in regards to the Foreign Keys. Note: this is a bit different than 1.0 as the navigation properties changed a bit to enable the ability to specify the primary key type:
We are trying to address some of the EF migration/extensibility issues, so things hopefully will be easier with Identity 1.1-alpha1 and the upcoming 6.0.2/6.1 EF releases, but I'm not sure the updated EF packages are available on myget yet.
var user = modelBuilder.Entity<TUser>()
.ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName).IsRequired();
modelBuilder.Entity<TUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles");
modelBuilder.Entity<TUserLogin>()
.HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey})
.ToTable("AspNetUserLogins");
modelBuilder.Entity<TUserClaim>()
.ToTable("AspNetUserClaims");
var role = modelBuilder.Entity<TRole>()
.ToTable("AspNetRoles");
role.Property(r => r.Name).IsRequired();
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);
The final (working) OnModelCreating method builds on the answer provided by Hao Kung (whose answer I have accepted and to whom I have awarded the bounty) to create the Foreign Key references from the IdentityUser/ApplicationUser side rather than attempting to do the same from the other direction.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var user = modelBuilder.Entity<IdentityUser>().HasKey(u => u.Id).ToTable("User", "Users"); //Specify our our own table names instead of the defaults
user.Property(iu => iu.Id).HasColumnName("Id");
user.Property(iu => iu.UserName).HasColumnName("UserName");
user.Property(iu => iu.Email).HasColumnName("EmailAddress").HasMaxLength(254).IsRequired();
user.Property(iu => iu.IsConfirmed).HasColumnName("EmailConfirmed");
user.Property(iu => iu.PasswordHash).HasColumnName("PasswordHash");
user.Property(iu => iu.SecurityStamp).HasColumnName("SecurityStamp");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName).IsRequired();
var applicationUser = modelBuilder.Entity<ApplicationUser>().HasKey(au => au.Id).ToTable("User", "Users"); //Specify our our own table names instead of the defaults
applicationUser.Property(au => au.Id).HasColumnName("Id");
applicationUser.Property(au => au.NumericId).HasColumnName("NumericId");
applicationUser.Property(au => au.UserName).HasMaxLength(50).HasColumnName("UserName");
applicationUser.Property(au => au.PasswordHash).HasColumnName("PasswordHash");
applicationUser.Property(au => au.SecurityStamp).HasColumnName("SecurityStamp");
applicationUser.Property(au => au.DisplayName).HasColumnName("DisplayName");
applicationUser.Property(au => au.Description).HasColumnName("Description");
applicationUser.Property(au => au.Email).HasColumnName("EmailAddress").HasMaxLength(254).IsRequired();
applicationUser.Property(au => au.IsConfirmed).HasColumnName("EmailConfirmed");
applicationUser.Property(au => au.Sequence).HasColumnName("Sequence");
applicationUser.Property(au => au.ExternalRef).HasColumnName("ExternalRef");
applicationUser.Property(au => au.LoggedOn).HasColumnName("LoggedOn");
applicationUser.Property(au => au.LoggedOff).HasColumnName("LoggedOff");
applicationUser.Property(au => au.LastActivity).HasColumnName("LastActivity");
applicationUser.Property(au => au.FailedLoginAttempts).IsOptional().HasColumnName("FailedLoginAttempts");
applicationUser.Property(au => au.LockedOutUntil).IsOptional().HasColumnName("LockedOutUntil");
applicationUser.Property(au => au.LockOutCycles).IsOptional().HasColumnName("LockOutCycles");
applicationUser.Property(au => au.Approved).HasColumnName("Approved");
var role = modelBuilder.Entity<IdentityRole>().HasKey(ir => ir.Id).ToTable("ApplicationRole", "Users");
role.Property(ir => ir.Id).HasColumnName("Id");
role.Property(ir => ir.Name).HasColumnName("Name");
var claim = modelBuilder.Entity<IdentityUserClaim>().HasKey(iuc => iuc.Id).ToTable("UserClaim", "Users");
claim.Property(iuc => iuc.Id).HasColumnName("Id");
claim.Property(iuc => iuc.ClaimType).HasColumnName("ClaimType");
claim.Property(iuc => iuc.ClaimValue).HasColumnName("ClaimValue");
claim.Property(iuc => iuc.UserId).HasColumnName("UserId");
var login = modelBuilder.Entity<IdentityUserLogin>().HasKey(iul => new { iul.UserId, iul.LoginProvider, iul.ProviderKey }).ToTable("UserLogin", "Users"); //Used for third party OAuth providers
login.Property(iul => iul.UserId).HasColumnName("UserId");
login.Property(iul => iul.LoginProvider).HasColumnName("LoginProvider");
login.Property(iul => iul.ProviderKey).HasColumnName("ProviderKey");
var userRole = modelBuilder.Entity<IdentityUserRole>().HasKey(iur => new { iur.UserId, iur.RoleId }).ToTable("UserRole", "Users");
userRole.Property(ur => ur.UserId).HasColumnName("UserId");
userRole.Property(ur => ur.RoleId).HasColumnName("RoleId");
}
I also liked the (brilliant yet so simple I can't think why I didn't do it before) idea of referencing the Model Builder Entity as a variable to use on each following fluent-api statement.
I referenced properties and foreign keys on both entities, although (in practice) it does not appear that this is required. On ASP.NET Identity 1.0 there was no problem omitting the property mappings, but since I have changed the names of Email and IsConfirmed database columns at least those needed to be mapped against the IdentityUser entity in ASP.NET Identity 1.1
Likewise the ApplicationUser class probably does not need to foreign key defined (as relationships are defined between the base class and the other entities) but I saw no harm in ensuring there was no assumption of additional foreign key columns on the other entity tables by adding a explicit definition - and it doesn't seem to have done any harm.
Not sure exactly what you are trying to achieve. It should be possible if you use the following as required:
Then when mapping foreign key fields , if you have a property that hold the Foreign key, tell ef
modelBuilder.Entity<T>().HasRequired(t => t.NAVPROP)
.WithMany()
.HasForeignKey(t => t.PropertyinTThatholdsFKID);
field_id is generated by EF when it sees a need to cater for a defined relationship and there was no defined foreignkey field. So either you have the an extra relationship you dont expect or want. Or the the relationhip was not specified with the foreignkey field.
See How can I change the table names when using Visual Studio 2013 ASP.NET Identity? for more information (bottom of initial question). I think you just need to call base.onModelCreating(modelBuilder) before your fluent calls.
BEFORE your fluent calls, add:
base.onModelCreating(modelBuilder);
As far as the SQL Scripts:
Update-Database -Script
Also here is a codeproject with the schema scripted out already (although I realize the table names are different).
Edit
My Overridden OnModelCreating Method (notice the call to base.OnModelCreating(modelBuilder) call at the beginning):
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("User");
modelBuilder.Entity<IdentityUser>().Property(iu => iu.Id).HasColumnName("Id");
modelBuilder.Entity<IdentityUser>().Property(iu => iu.UserName).HasColumnName("UserName");
/*IdentityUser does not have an Email property
modelBuilder.Entity<IdentityUser>().Property(iu => iu.Email).HasColumnName("EmailAddress").HasMaxLength(254).IsRequired(); Not sure where this is from?*/
modelBuilder.Entity<IdentityUser>().Property(iu => iu.PasswordHash).HasColumnName("PasswordHash");
modelBuilder.Entity<IdentityUser>().Property(iu => iu.SecurityStamp).HasColumnName("SecurityStamp");
/*Same - dont know where this is from?
modelBuilder.Entity<IdentityUser>().Property(iu => iu.IsConfirmed).HasColumnName("Confirmed");*/
modelBuilder.Entity<ApplicationUser>().HasKey(au => au.Id).ToTable("User"); //Specify our our own table names instead of the defaults
modelBuilder.Entity<ApplicationUser>().Property(au => au.Id).HasColumnName("Id");
modelBuilder.Entity<ApplicationUser>().Property(au => au.NumericId).HasColumnName("NumericId");
modelBuilder.Entity<ApplicationUser>().Property(au => au.UserName).HasMaxLength(50).HasColumnName("UserName");
modelBuilder.Entity<ApplicationUser>().Property(au => au.SecurityStamp).HasColumnName("SecurityStamp");
modelBuilder.Entity<ApplicationUser>().Property(au => au.DisplayName).HasColumnName("DisplayName");
modelBuilder.Entity<ApplicationUser>().Property(au => au.Description).HasColumnName("Description");
modelBuilder.Entity<ApplicationUser>().Property(au => au.Sequence).HasColumnName("Sequence");
modelBuilder.Entity<ApplicationUser>().Property(au => au.ExternalRef).HasColumnName("ExternalRef");
modelBuilder.Entity<ApplicationUser>().Property(au => au.LoggedOn).HasColumnName("LoggedOn");
modelBuilder.Entity<ApplicationUser>().Property(au => au.LoggedOff).HasColumnName("LoggedOff");
modelBuilder.Entity<ApplicationUser>().Property(au => au.LastActivity).HasColumnName("LastActivity");
modelBuilder.Entity<ApplicationUser>().Property(au => au.FailedLoginAttempts).IsOptional().HasColumnName("FailedLoginAttempts");
modelBuilder.Entity<ApplicationUser>().Property(au => au.LockedOutUntil).IsOptional().HasColumnName("LockedOutUntil");
modelBuilder.Entity<ApplicationUser>().Property(au => au.LockOutCycles).IsOptional().HasColumnName("LockOutCycles");
modelBuilder.Entity<ApplicationUser>().Property(au => au.Approved).HasColumnName("Approved");
modelBuilder.Entity<IdentityRole>().HasKey(ir => ir.Id).ToTable("ApplicationRole");
modelBuilder.Entity<IdentityRole>().Property(ir => ir.Id).HasColumnName("Id");
modelBuilder.Entity<IdentityRole>().Property(ir => ir.Name).HasColumnName("Name");
modelBuilder.Entity<IdentityUserClaim>().HasKey(iuc => iuc.Id).ToTable("UserClaim");
modelBuilder.Entity<IdentityUserClaim>().Property(iuc => iuc.Id).HasColumnName("Id");
modelBuilder.Entity<IdentityUserClaim>().Property(iuc => iuc.ClaimType).HasColumnName("ClaimType");
modelBuilder.Entity<IdentityUserClaim>().Property(iuc => iuc.ClaimValue).HasColumnName("ClaimValue");
//modelBuilder.Entity<IdentityUserClaim>().Property(iuc => iuc.UserId).HasColumnName("UserId");
modelBuilder.Entity<IdentityUserLogin>().HasKey(iul => new { iul.UserId, iul.LoginProvider, iul.ProviderKey }).ToTable("UserLogin"); //Used for third party OAuth providers
modelBuilder.Entity<IdentityUserLogin>().Property(iul => iul.UserId).HasColumnName("UserId");
modelBuilder.Entity<IdentityUserLogin>().Property(iul => iul.LoginProvider).HasColumnName("LoginProvider");
modelBuilder.Entity<IdentityUserLogin>().Property(iul => iul.ProviderKey).HasColumnName("ProviderKey");
modelBuilder.Entity<IdentityUserRole>().HasKey(iur => new { iur.UserId, iur.RoleId }).ToTable("UserRole");
modelBuilder.Entity<IdentityUserRole>().Property(ur => ur.UserId).HasColumnName("UserId");
modelBuilder.Entity<IdentityUserRole>().Property(ur => ur.RoleId).HasColumnName("RoleId");
}