0

I found this piece does not work properly:

protected override void Seed(PintxoLista.Models.ApplicationDbContext context)
{
    var store = new RoleStore<IdentityRole>(context);
    var manager = new RoleManager<IdentityRole>(store);
    if (!context.Roles.Any(r => r.Name == "WeddingGuest"))
    {
        var role = new IdentityRole { Name = "WeedingGuest" };
        manager.Create(role);
    }

    if (!context.Roles.Any(r => r.Name == "BrideGroom"))
    {
        var role = new IdentityRole { Name = "BrideGroom" };
        manager.Create(role);
    }

    if (System.Diagnostics.Debugger.IsAttached == false)
    {
        System.Diagnostics.Debugger.Launch();
    }

    context.Users.AddOrUpdate(i => i.Id,
        new ApplicationUser
    {
        Id = "1",
        UserName = "han",
        Email = "hansolo1@rebels.com",
        PasswordHash = new PasswordHasher().HashPassword("1"),
        SecurityStamp = string.Empty
    },
    new ApplicationUser
    {
        Id = "2",
        UserName = "lando",
        Email = "lando@rebels.com",
        PasswordHash = new PasswordHasher().HashPassword("1"),
        SecurityStamp = string.Empty
    });

    var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
    userManager.AddToRole("1", "WeedingGuest");
    userManager.AddToRole("2", "BrideGroom");
}

The roles are created but the users are not and then the first AddToRole fails. Instead, if the users are add (or updated) to the database first then it works fine.

protected override void Seed(PintxoLista.Models.ApplicationDbContext context)
{
    context.Users.AddOrUpdate(i => i.Id,
        new ApplicationUser
    {
        Id = "1",
        UserName = "han",
        Email = "hansolo1@rebels.com",
        PasswordHash = new PasswordHasher().HashPassword("1"),
        SecurityStamp = string.Empty
    }, new ApplicationUser
    {
        Id = "2",
        UserName = "lando",
        Email = "lando@rebels.com",
        PasswordHash = new PasswordHasher().HashPassword("1"),
        SecurityStamp = string.Empty
    });

    var store = new RoleStore<IdentityRole>(context);
    var manager = new RoleManager<IdentityRole>(store);
    if (!context.Roles.Any(r => r.Name == "WeddingGuest"))
    {
        var role = new IdentityRole { Name = "WeedingGuest" };
        manager.Create(role);
    }

    if (!context.Roles.Any(r => r.Name == "BrideGroom"))
    {
        var role = new IdentityRole { Name = "BrideGroom" };
        manager.Create(role);
    }

    var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
    userManager.AddToRole("1", "WeedingGuest");
    userManager.AddToRole("2", "BrideGroom");
}

Can anyone explain this apparently strange behaviour? Why the users must be created first? Thank you!!

Julen
  • 1,574
  • 3
  • 22
  • 38

2 Answers2

2

A user must be created before that user can be added to a role. It would be impractical to add a non-existent user to a role.

Scott Prokopetz
  • 474
  • 3
  • 6
0

I couldn't recreated your scenario, the seed function didn't save the data in any order. But this is what I figured out.

The reason why it's saying "UserId not found" and the action isn't working is because everything is running in the same transaction.

The UserManager cannot link an user with a role because the user hasn't been created yet. You need to finish the current transaction (the user will be added to the DB) and start a new one, then you can add the roles to the user.

See the code below

protected override void Seed(MyProject.Dal.Context.MyProjectDbContext context)
    {
        context.Users.AddOrUpdate(u => u.Id, new Core.Entities.ApplicationUser{
             Id = "1",
             UserName = "foo@a.com",
             Email = "foo@a.com",
             PasswordHash = new PasswordHasher().HashPassword("@edulopezTest"),
             SecurityStamp = string.Empty,
             Names = "Test",
             LastNames = "Admin",
             BirthDate = DateTime.Now,
         });

       var  RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
       if (!context.Roles.Any(r => r.Name == "SuperAdmin"))
       {
           var role = new IdentityRole { Name = "SuperAdmin" };
           RoleManager.Create(role);
       }

       //**********************************************************
       //THIS IS ANOTHER WAY TO ADD THE ROLES. IT GIVE SAME RESULTS
       //**********************************************************
       //context.Roles.AddOrUpdate(r => r.Name,
       //    new IdentityRole { Name = "SuperAdmin" }    // 1
       //   , new IdentityRole { Name = "Admin" }         // 2
       //   );  

    var userManager = new UserManager<Core.Entities.ApplicationUser>(new UserStore<Core.Entities.ApplicationUser>(context));          
    userManager.AddToRole("1", "SuperAdmin");
    }

To finish the current transaction and start a new one you just need to call "SaveChanges" from the current context.

see changes on the code below

context.SaveChanges(); // <-- Finish and start a new one
var userManager = new UserManager<Core.Entities.ApplicationUser>(new UserStore<Core.Entities.ApplicationUser>(context));          
userManager.AddToRole("1", "SuperAdmin");

I used this links as reference but mostly was by doing tests.

http://blog.oneunicorn.com/2013/05/28/database-initializer-and-migrations-seed-methods/ https://msdn.microsoft.com/en-us/data/jj554735

EduLopez
  • 721
  • 7
  • 18
  • Thanks for your response. Truth is this I have forgotten this issue. I will try to get back at it in the future. Thanks again for your time! – Julen Mar 31 '15 at 07:46
  • Thanks to you too. Hope it solve your problem. If that happen, please mark it as a solution :). – EduLopez Apr 06 '15 at 15:59