EFcore with IdentityDbContext and hasData seeding creates IdentityRole

.net-core c# ef-migrations entity-framework-core

Question

I am a bit dazzled; I am using dotnet core (2.1) EF with migrations. When I create the first migration just based upon the context, it all looks OK actually.

so I have a context like:

public class DataContext : IdentityDbContext<User, IdentityRole<Guid>, Guid>
{

    public virtual DbSet<Country> Countries { get; set; }
    public virtual DbSet<CountryUser> CountryUsers { get; set; }
    //..more stuff

    public DataContext(DbContextOptions options) : base(options)
    { }
}

so after creating the migrations it wants to add:

migrationBuilder.CreateTable(
            name: "AspNetRoles",
            columns: table => new
            {
                Id = table.Column<Guid>(nullable: false),
                Name = table.Column<string>(maxLength: 256, nullable:
                //etc. etc. Removed rest of migrations.

All good I thought.

Then i started to follow the following article; How to seed an Admin user in EF Core 2.1.0?

After setting the HasData and seeding the DB, created a new migration, it created a new migration where it wanted to drop the AspNetRoles table and creates as new table IdentityRole. I just deleted the DB and tried to do it again, and now it only wants to insert the data when seeding. But i cannot figure out what I changed and even better, why it wanted to drop and create different tables.

can somebody explain when it wants to create AspNetRoles and when it wants to create IdentityRoles (and along the other tables that goes with it).

Just to be sure; the context was always extending from

: IdentityDbContext<User, IdentityRole<Guid>, Guid>

and my User:

public class User : IdentityUser<Guid>
{
    public virtual ICollection<CountryUser> CountryUsers { get; set; }
}

thnx!!

1
1
11/27/2018 11:42:20 AM

Accepted Answer

As I understand, you are following the following approach:

modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "Admin", NormalizedName = "Admin".ToUpper() });

There are two problems with this code.

The first is the usage of modelBuilder.Entity<IdentityRole>(). This makes IdentityRole class to be treated by EF Core as an entity, hence the IdentityRoles table it tries to create. It's because IdentityRole class is different from what your model is using - IdentityRole<Guid>. Change it to modelBuilder.Entity<IdentityRole<Guid>>() (and also the new operator) and the problem will be solved.

The second problem is that HasData requires PK values to be specified, as explained in the Data Seeding section of the EF Core documentation:

The primary key value needs to be specified even if it's usually generated by the database. It will be used to detect data changes between migrations.

So additionally to changing the HasData generic type argument, you need to pre generate Guid to be used as Id for the new role (see Entity Framework Core Auto Generated guid for more details a the similar issue) and use something like this:

modelBuilder.Entity<IdentityRole<Guid>>().HasData(
    new IdentityRole<Guid>
    {
        Id = new Guid("pre generated value"),
        Name = "Admin",
        NormalizedName = "Admin".ToUpper()
    }
);
4
11/27/2018 11:42:10 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow