How can I avoid ASP.NET Identity from adding this extra field? - ef-code-first

I have a new MVC5 project with ASP.NET Identity 2.0 and EF 6.1.1.
I added my own ApplicationUser (based on built-in IdentityUser). This is how my DbContext is created.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
When the database is created I have tables like AspNetUsers, AspNetUserRoles, AspNetUserClaims, and AspNetUserLogins. Then I added OnModelCreating() with just the most basic statements.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}
As soon as I add OnModelCreating(), the identity tables are automatically renamed to ApplicationUsers, IdentityUserRoles, IdentityUserClaims, and IdentityUserLogins. That's fine with me (and I know how to rename them).
But what I don't like: All of a sudden, IdentityUserRoles, IdentityUserClaims, and IdentityUserLogins have an extra field called "ApplicationUser_Id". The original "AspNetXXX" tables didn't have such a field.
Why is that? And is there anything I can do in order to avoid this?

You need to call base.OnModelCreating. There are a number of additional things OnModelCreating does in IdentityDbContext that you may be missing without calling it - the default names of the tables being one of them.
Its best to call it first, then apply your own changes afterwards.

As mentioned by Matt Lassam-Jones
worked for me also and Thank You.
public class NebulaContext : IdentityDbContext<ApplicationUser>
{
public NebulaContext()
: base("Name=MyEntity", throwIfV1Schema: false)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); //Optional
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();//Optional
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); //Optional
base.OnModelCreating(modelBuilder);
}
}

Related

Renamed default tables but AspNetusers Table Still Getting Created

I am working with ASP.NET identity. I renamed the default tables using the following code.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("Users");
modelBuilder.Entity<IdentityRole>().ToTable("Roles");
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");
modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
}
}
}
But when I run my app, AspnetUsers is still created but with a single column named 'Id'. This table is being populated along with the new "Users" table. Why? And how do I stop this behavior.
I see the same question asked here, but without a good response: Identity 2.0 Code First Table Renaming
I hope I am not violating StackOverflow's guidelines in reasking this question/// if so apologies in advance!
Stumbled across this post when looking for a quick solution - now I've dug a bit through the code and found the answer; maybe it helps someone.
I suppose you have overwritten the default IdentityUser class, right?
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
...
In that case, you'll have to exclude the default IdentityUser from the ModelBuilder:
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//modelBuilder.Entity<IdentityUser>().ToTable("Users", "dbo"); // we have overwritten IdentityUser, so no more need for the empty AspNetUsers table
modelBuilder.Entity<ApplicationUser>().ToTable("Users", "dbo"); // Use ApplicationUser instead
modelBuilder.Entity<IdentityRole>().ToTable("Roles", "dbo");

Auto-increment IDs after importing data in the Entity Framework

I'm developing a new version of an old application using Entity Framework 6 Code First and ASP.NET with SQL Server 2014 as the back end. The old database is an Access database and has about a dozen tables with auto-increment IDs. I want to import the old data while keeping the IDs intact so that the relationships between the tables is preserved. I've set the key attribute on the new entities to
DatabaseGeneratedOption.None
This works, and I'm able to import all of the values from the old database, however I'd like to have the primary keys auto-increment from this point on. Since the DatabaseGeneratedOption is set to None it seems that I have to manually generate IDs in
You probably want to set the keys as identity as they were and then disable the identity-constraint during import.
You do this with SET IDENTITY_INSERT tablename ON before the insert statement. Dont forget to set it to OFF when you are done.
I never tried this, but you can have different configurations and switch them as per requirement/environment, hope this helps
public class IdentityDbConfiguration : EntityTypeConfiguration<Foo>
{
public IdentityDbConfiguration()
{
Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class DbConfiguration : EntityTypeConfiguration<Foo>
{
public DbConfiguration()
{
Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
public class AppContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new IdentityDbConfiguration());
}
}
public class AppContext2 : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DbConfiguration());
}
}

Renaming dbo.AspNetUsers table

I'm trying to rename the default table names generated by ASP.net Identity 2.0. I read all the articles, the questions and the answers on stackoverflow but im still getting the same error.
I renamed the tables to Roles, UserClaims, Logins, UserRoles and Users. I also changed the application dbcontext to the following
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("Users", "dbo");
modelBuilder.Entity<IdentityRole>().ToTable("Roles", "dbo");
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles", "dbo");
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims", "dbo");
modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins", "dbo");
}
}
But i keep getting the Invalid object name 'dbo.AspNetUsers'. error, and I have no idea why its still trying to locate AspNetUsers in the first place instead of just Users although i made the changes above. Totally desperate by now.
The database as well, same columns with the new table names:
And the SQL database project:
You need to update database. Enable-Migrations and Update-Database, explained in details here. The point of EF code first approach is to write our model classes and configurations and each time we change something we use EF migrations to update the database schema.
Database first approach with asp.net-identity-entityframework are explained here and here, not so straightforward
Write the following code in IdentityModels.cs
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DBConnectionString", throwIfV1Schema: false)
{
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims");
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles");
modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins");
modelBuilder.Entity<IdentityRole>().ToTable("Roles");
modelBuilder.Entity<ApplicationUser>().ToTable("Users");
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Write the following code in Application_Start() Method in Global.asax.cs file
Database.SetInitializer<ApplicationDbContext>(null);

Model change detection ASP.NET code first migrations

I have added
public IEnumerable<Comment> Comments { get; set; }
to a Model in an ASP.net MVC project. I ran the following to generate a migration in the package console
PM> Add-Migration AddCommentsToDevice
and the resulting migration did not pick up the change to the model
public partial class AddCommentsToDevice : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Any tips on the syntax of the migrations or what causes detections?
You've added to little. You need to configure the relationship properly - the best with fluent api. Use this for navigation property:
public virtual ICollection<Comment> Comments { get; set; }
Important - always use ICollection, not IEnumerable for Navigation properties and make them virtual - thanks to this ef will be able to track changes.
Then in your DbContext you add following code:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Model>().HasKey(x => x.Id);
modelBuilder.Entity<Model>().HasMany(x => x.Comments);
base.OnModelCreating(modelBuilder);
}
I assumed that class related to Comments is named Model.

ASP.NET Identity - Error when changing User ID Primary Key default type from string to int AND when using custom table names

I'm using Microsoft.AspNet.Identity 2.0.0-beta1 and Entity Framework 6.1.0-beta1 (released 11 Feb 2014).
I'm getting the following error when I try to change the default type of User ID Primary Key from string to int AND when I try to use custom table names (so User.MyUsers instead of dbo.AspNetUsers):
"The entity types 'IdentityUser' and 'ApplicationUser' cannot share table 'MyUsers' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them."
I can successfully change the default type of User ID PK from string to int OR change the default identity table names but I cannot do both together without hitting this error.
My solution is based on:
1: Section "Make the type of Primary Key be extensible for Users and Roles" from http://blogs.msdn.com/b/webdev/archive/2013/12/20/announcing-preview-of-microsoft-aspnet-identity-2-0-0-alpha1.aspx.
2: How can I change the table names when using Visual Studio 2013 ASP.NET Identity?.
My actual code is:
using Microsoft.AspNet.Identity.EntityFramework;
namespace Musetone.Models
{
public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
}
public class CustomRole : IdentityRole<int, CustomUserRole>
{
public CustomRole() { }
public CustomRole(string name) { Name = name; }
}
public class CustomUserRole : IdentityUserRole<int> { }
public class CustomUserClaim : IdentityUserClaim<int> { }
public class CustomUserLogin : IdentityUserLogin<int> { }
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>().ToTable("MyUsers", "User").HasKey(u => u.Id).Property(u => u.Id).HasColumnType("int");
modelBuilder.Entity<ApplicationUser>().ToTable("MyUsers", "User").HasKey(u => u.Id).Property(u => u.Id).HasColumnType("int");
modelBuilder.Entity<IdentityUserRole>().ToTable("MyUserRoles", "User").HasKey(r => new { r.RoleId, r.UserId }).Property(r => r.UserId).HasColumnType("int");
modelBuilder.Entity<IdentityUserLogin>().ToTable("MyUserLogins", "User").HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey }).Property(l => l.UserId).HasColumnType("int");
modelBuilder.Entity<IdentityUserClaim>().ToTable("MyUserClaims", "User").Property(c => c.UserId).HasColumnType("int");
modelBuilder.Entity<IdentityRole>().ToTable("MyRoles", "User").HasKey(r => r.Id);
}
}
}
I get this error even if I remove HasColumnType("int").
Any help would be greatly appreciated.
I think the mapping might be incorrect. While defining the ApplicationDbContext class, you are using the custom classes defined for roles, logins and claims for generic but passing the base classes for mapping the tables. For the ChangePK example the following mapping worked for me. Let me know if this works for you too. The mapping should be simple enough
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().ToTable("MyUsers");
modelBuilder.Entity<CustomUserRole>().ToTable("MyUserRoles");
modelBuilder.Entity<CustomUserLogin>().ToTable("MyUserLogins");
modelBuilder.Entity<CustomUserClaim>().ToTable("MyUserClaims");
modelBuilder.Entity<CustomRole>().ToTable("MyRoles");
}

Resources