capiono
capiono

Reputation: 2997

Seeding asp.net core Identity Role

I'm trying to seed the AspNetRole table with initial system roles.

Seeding Extension:

public static void EnsureRolesAreCreated(this IApplicationBuilder app) {
        Dictionary<string, string> roles = new Dictionary<string, string>
        {
            { "Administrator", "Global Access." },
            { "User", "Restricted to business domain activity." }
        };

        var context = app.ApplicationServices.GetService<ApplicationDbContext>();
        if (context.AllMigrationsApplied()) {
            var roleManager = app.ApplicationServices.GetService<ApplicationRoleManager>();
            foreach (var role in roles) {
                if (!roleManager.RoleExistsAsync(role.Key).Result) {
                    roleManager.CreateAsync(new ApplicationRole() { Name = role.Key, System = true, Description = role.Value });
                }
            }
        }
    }

which is called in startup class: app app.EnsureRolesAreCreated();

when the code above runs, the CreateAsync function throws an Exception:

{Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'Id', table 'AspNetRoles'; column does not allow nulls. INSERT fails. The statement has been terminated.

I have tried This and this, still not working.

services.AddIdentity<ApplicationUser, ApplicationRole>(config => {
            config.User.RequireUniqueEmail = true;
            config.Lockout = new LockoutOptions {
                AllowedForNewUsers = true,
                DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30),
                MaxFailedAccessAttempts = 5
            };
            config.Password = new PasswordOptions {
                RequireDigit = true,
                RequireNonAlphanumeric = false,
                RequireUppercase = true,
                RequireLowercase = true,
                RequiredLength = 12,
            };
        })
        .AddEntityFrameworkStores<ApplicationDbContext, int>()
        .AddUserValidator<ApplicationUserValidator<ApplicationUser>>()
        .AddUserManager<ApplicationUserManager>()
        .AddRoleManager<ApplicationRoleManager>()
        .AddDefaultTokenProviders();



public class ApplicationUser : IdentityUser<int> {}
public class ApplicationRole : IdentityRole<int> {}


protected override void OnModelCreating(ModelBuilder modelBuilder) {

        modelBuilder.Entity<ApplicationUser>(i => {
            i.HasKey(x => x.Id);
            i.Property(x => x.Id).ValueGeneratedOnAdd();
        });
        modelBuilder.Entity<ApplicationRole>(i => {
            i.HasKey(x => x.Id);
            i.Property(x => x.Id).ValueGeneratedOnAdd();
        });
        modelBuilder.Entity<IdentityUserRole<int>>(i => {
            i.HasKey(x => new { x.RoleId, x.UserId });
        });

        modelBuilder.Entity<IdentityUserLogin<int>>(i => {
            i.HasKey(x => new { x.ProviderKey, x.LoginProvider });
        });

        modelBuilder.Entity<IdentityRoleClaim<int>>(i => {
            i.HasKey(x => x.Id);
            i.Property(x => x.Id).ValueGeneratedOnAdd();
        });

        modelBuilder.Entity<IdentityUserClaim<int>>(i => {
            i.HasKey(x => x.Id);
            i.Property(x => x.Id).ValueGeneratedOnAdd();
        });
   }

I added ValueGeneratedOnAdd() in an attempt to force the ID generation.

Upvotes: 3

Views: 1445

Answers (1)

capiono
capiono

Reputation: 2997

I found the issue. I was missing:

base.OnModelCreating(modelBuilder);

at the beginning of the ModelCreating function

 protected override void OnModelCreating(ModelBuilder modelBuilder){
        base.OnModelCreating(modelBuilder);
 }

after making that change, I did a migration and the ID column is now created as an Identity Column

[Id] [int] IDENTITY(1,1) NOT NULL

Upvotes: 5

Related Questions