Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Seeding with Identity (Microsoft.Owin.Security) user

I have a class that seed the database which add 2 users with roles and custom fields. The problem I have is that it save the data in [dbo].[AspNetUsers] instead of [dbo].[IdentityUsers]. Both tables are created. When seeded, the data go into AspNetUser. When I launch the web site, and register a new user, the data go into IdentityUser.

Here is the Migration class :

internal sealed class Configuration : DbMigrationsConfiguration<DatabaseContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(DatabaseContext context)
    {
        base.Seed(context);

        var userStore = new UserStore<ApplicationUser>();
        var manager = new UserManager<ApplicationUser>(userStore);

        var role = new IdentityUserRole { Role = new IdentityRole(Model.Roles.ADMINISTRATOR) };
        var user = new ApplicationUser() { UserName = "123123", Email = "[email protected]", Language = "en-US"};
        user.Roles.Add(role);
        IdentityResult result = manager.Create(user, "123123");

        var role2 = new IdentityUserRole { Role = new IdentityRole(Model.Roles.NORMAL) };
        var user2 = new ApplicationUser() { UserName = "qweqwe", Email = "[email protected]", Language = "fr-CA" };
        user.Roles.Add(role2);
        IdentityResult result2 = manager.Create(user2, "qweqwe");
    }
}

Here is the ApplicationUser class which define custom field for the Identity model.

public class ApplicationUser : IdentityUser, ICurrentUser
{
    public ApplicationUser()
    {
        Email = "";
        Language = "";
    }
    public string UserId {
        get { return base.Id; }
        set{} 
    }
    public string Email { get; set; } 
    public string Language { get; set; } 

}

Here is the Entity Framework configuration class for this new class.

public class ApplicationUserConfiguration : EntityTypeConfiguration<ApplicationUser>
{
    public ApplicationUserConfiguration()
    {
        this.HasKey(d => d.Id);
        this.Ignore(d => d.UserId);
    }
}

enter image description here

Both are using the save DataContext with the same configuration:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //... others entity here

        modelBuilder.Configurations.Add(new ApplicationUserConfiguration());

        //Theses configuration are required since custom fields are added to ApplicationUser. Here is why : http://stackoverflow.com/questions/19474662/map-tables-using-fluent-api-in-asp-net-mvc5-ef6
        modelBuilder.Entity<IdentityUserLogin>().HasKey(l => l.UserId);
        modelBuilder.Entity<IdentityRole>().HasKey(r => r.Id);
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });

    }

My question are: Why do I have AspNet prefixe tables name that is duplicated from Identity tables? Why does the seed use one while the web application use the other?

like image 535
Patrick Desjardins Avatar asked Dec 24 '13 01:12

Patrick Desjardins


1 Answers

Are your DbContext inheriting from IdentityDbContext?

If you inherit from IdentityDbContext you should not need any additional configuration in your OnModelCreating. The mappings provided by the IdentityDbContext and the default Entity Framework conventions should suffice.

If you declare your ApplicationUser without a setter for the UserId, then you won't need to ignore the UserId property:

public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        Email = "";
        Language = "";
    }

    public string Email { get; set; }
    public string Language { get; set; }

    public string UserId
    {
        get { return Id; }
    }
}

Then your ApplicationDbContext can be as simple as this (I have renamed your Configuration class to MigrationConfiguration for clarity) :

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    static ApplicationDbContext()
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, MigrationConfiguration>());
    }

    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }
}

This works as expected (only tables named AspNetXXXX, the AspNetUsers table has the custom fields) with the release versions (Version 1.0.0) of the AspNet.Identity.Core and AspNet.Identity.EntityFramework assemblies. enter image description here

like image 161
Olav Nybø Avatar answered Sep 19 '22 12:09

Olav Nybø