Search code examples
c#asp.net-coreentity-framework-coreasp.net-identityrazor-pages

How do I initialize database with default values in .net6


Till .net5 I've been Seeding data using the following in startup.cs file:

SeedData.Seed(_userManager, _roleManager);

And then in a seperate file SeedData.cs, the following code:

public static class SeedData
{
    public static void Seed(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
    {
        SeedRoles(roleManager);
        SeedUsers(userManager);
    }

    private static void SeedUsers(UserManager<IdentityUser> userManager)
    {
        if(userManager.FindByNameAsync("[email protected]").Result == null)
        {
            var user = new IdentityUser
            {
                UserName = "[email protected]",
                Email = "[email protected]"
            };

            var result = userManager.CreateAsync(user, "P@ssword1").Result;
            if(result.Succeeded)
            {
                userManager.AddToRoleAsync(user, "Administrator").Wait();
            }
        }
    }
    private static void SeedRoles(RoleManager<IdentityRole> roleManager)
    {
        if(!roleManager.RoleExistsAsync("Administrator").Result)
        {
            var role = new IdentityRole
            {
                Name = "Administrator",
            };
            var result = roleManager.CreateAsync(role).Result;
        }

        if(!roleManager.RoleExistsAsync("Employee").Result)
        {
            var role = new IdentityRole
            {
                Name = "Employee",
            };
            var result = roleManager.CreateAsync(role).Result;
        }
    }
}

Now, how do i do the same with .net6, since it has only program.cs file?


Solution

  • This is what I personally do:

    I make an extension to IApplicationBuilder:

    public static class ApplicationBuilderExtensions
        {
            public static async Task<IApplicationBuilder> PrepareDatabase(this IApplicationBuilder app)
            {
                using var scopedServices = app.ApplicationServices.CreateScope();
    
            var serviceProvider = scopedServices.ServiceProvider;
            var data = serviceProvider.GetRequiredService<NeonatologyDbContext>();
    
            data.Database.Migrate();
    
            await SeedAdministratorAsync(serviceProvider);
            await SeedDoctorAsync(data, serviceProvider);
    
    
            return app;
        }
    

    Here are the seedings:

     private static async Task SeedDoctorAsync(NeonatologyDbContext data, IServiceProvider serviceProvider)
            {
                if (data.Doctors.Any())
                {
                    return;
                }
    
                var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
                var roleManager = serviceProvider.GetRequiredService<RoleManager<ApplicationRole>>();
    
                var identityRole = new ApplicationRole()
                {
                    Name = DoctorRoleName
                };
    
                await roleManager.CreateAsync(identityRole);
    
                var city = await data.Cities.Where(x => x.Name == "Плевен").FirstOrDefaultAsync();
                var doctor = new ApplicationUser()
                {
                    Email = DoctorEmail,
                    UserName = DoctorEmail,
                    EmailConfirmed = true,
                    Doctor = new Doctor
                    {
                        FirstName = DoctorFirstName,
                        LastName = DoctorLastName,
                        PhoneNumber = DoctorPhone,
                        Address = Address,
                        Age = DoctorAge,
                        Biography = Biography,
                        CityId = city.Id,
                        City = city,
                        YearsOfExperience = YearsOfExperience,
                        Email = DoctorEmail
                    }
                };
    
                await userManager.CreateAsync(doctor, DoctorPassword);
                await userManager.AddToRoleAsync(doctor, identityRole.Name);
    
                doctor.Doctor.UserId = doctor.Id;
    
                doctor.Doctor.Image = new Image()
                {
                    RemoteImageUrl = "SomeURL"
                };
    
                await data.SaveChangesAsync();
            }
    
    private static async Task SeedAdministratorAsync(IServiceProvider serviceProvider)
            {
                var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
                var roleManager = serviceProvider.GetRequiredService<RoleManager<ApplicationRole>>();
    
                if (await roleManager.RoleExistsAsync(AdministratorRoleName))
                {
                    return;
                }
    
                var identityRole = new ApplicationRole()
                {
                    Name = AdministratorRoleName
                };
    
                await roleManager.CreateAsync(identityRole);
    
                const string adminEmail = AdministratorEmail;
                const string adminPassword = AdministratorPassword;
    
                var adminUser = new ApplicationUser()
                {
                    Email = adminEmail,
                    UserName = adminEmail,
                    EmailConfirmed = true
                };
    
                if (await userManager.IsInRoleAsync(adminUser, identityRole.Name))
                {
                    return;
                }
    
                await userManager.CreateAsync(adminUser, adminPassword);
                await userManager.AddToRoleAsync(adminUser, identityRole.Name);
            }
    

    And in the Program.cs I have:

    app.PrepareDatabase()
                    .GetAwaiter()
                    .GetResult();
    

    The following snippet works for me and seeds the data upon initialization of the application.