aspnet / Identity

[Archived] ASP.NET Core Identity is the membership system for building ASP.NET Core web applications, including membership, login, and user data. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
1.96k stars 869 forks source link

ASP.NET Core RC2 Seed Data using Services #832

Closed kjanshair closed 7 years ago

kjanshair commented 8 years ago

I've been using ASP.NET 5 RC1 in which I've an application in which I seed administrative credentials into the data base using Services as follows:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
                .AddSqlServer()
                .AddDbContext<ApplicationDbContext>(options => 
                    options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<AdministratorUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        services.AddTransient<AdministratorSeedData>();
    }

Here is the connection string sub-object:

"ConnectionString": "Server=.;Database=kjanshair;Trusted_Connection=True;"

And the service that I use to seed data is being seeded using the Administrative seed data. It all works fine but when I port it to RC2, with the following changes in the startup as:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options => 
            options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        services.AddTransient<AdministratorSeedData>();
    }

with the connection string as:

"ConnectionString": "Server=.;Database=_CHANGE_ME;Trusted_Connection=True;"

I get an exception in Configure() method

    public async void Configure(IApplicationBuilder app, AdministratorSeedData seeder)
    {
        app.UseIdentity();

        app.UseMvcWithDefaultRoute();

        await seeder.EnsureSeedData(); //Here exception occurs
    }

saying:

Message = "Cannot open database \"_CHANGE_ME\" requested by the login. The login failed.\r\nLogin failed for user 'DESKTOP-55E4D9H\\Janshair Khan'."

Why Am I getting this error? I've looked all over the alternatives but couldn't resolved.

Sorry for not proper formatting the code.

divega commented 8 years ago

@kjanshair how does the AdministratorSeedData class and your ApplicationDbContext look like? In particular I am interested in the constructors and the EnsureSeedData() method, but there may be other relevant parts, e.g. do you have an OnConfiguring() method on the DbContext?

PS: you may want to check out how I fixed the code formating on your post.

divega commented 8 years ago

Also, it may be obvious, but is the change of the database name in the connection string intentional?

kjanshair commented 8 years ago

@divega here is my EnsureSeedData() method

        public async Task EnsureSeedData()
        {
            if (await _userManager.FindByEmailAsync("someone@someone.com") == null)
            {
                ApplicationUser administrator = new ApplicationUser
                {
                    UserName = "someone@someone.com",
                    Email = "someone@someone.com"
                };

                await _roleManager.CreateAsync(new IdentityRole("Administrator"));
                await _userManager.CreateAsync(administrator, "Password123!");

                IdentityResult result = await _userManager.AddToRoleAsync(administrator, "Administrator");
            }
        }

and here is my Context class

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            :base(options)
        {

        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
        }
    }
ngohungphuc commented 7 years ago

Put this in Startup.cs file

using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                serviceScope.ServiceProvider.GetService<ApplicationDbContext>().SeedUser();
            }

Create a helper class like this and put everything you want to seed in it

public static async void SeedUser(this ApplicationDbContext context)
        {
            string[] roles = new string[] { "Administrator", "Manager", "Developer", "Accountant", "Designer", "Client", "Watcher" };

            foreach (var role in roles)
            {
                var roleStore = new RoleStore<IdentityRole>(context);
                //add default  role to db
                if (!context.Roles.Any(r => r.Name == role))
                {
                    await roleStore.CreateAsync(new IdentityRole(role));
                }
            }

        }
HaoK commented 7 years ago

@ngohungphuc 's code should work