为什么数据库没有播种?

时间:2015-04-12 06:00:06

标签: ef-code-first asp.net-identity-2

好吧,我是asp.net身份的新手。现在有一项任务是提供一些种子数据(具有管理员角色的用户)。尝试使用类似Asp identity samples的代码。

我有一些静态类,它有几种播种数据的方法,大多数使用本机EF更新工具(DbSet.AddOrUpdate),这些工作正常。最后一个使用新的身份API:

private static void InitRolesAndAdminProfile(PortalContext context)
        {
            var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
            var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
            const string name = "webadmin";
            const string email = "webadmin@mail.ru";
            const string password = "StrongKeyword1";
            var rolenames = new[]
            {
                "Administrator",
                "Judge",
                "Competitor",
                "Member"
            }; 
     foreach (string rolename in rolenames)
            {
                CustomIdentityRole role = roleManager.FindByName(rolename);
                if (role == null)
                {
                    role = new CustomIdentityRole { Name = rolename };
                    IdentityResult roleresult = roleManager.Create(role);
                }
            }

            UserProfile user = userManager.FindByName(name);
            if (user == null)
            {
                user = new UserProfile { UserName = name, Email = "webadmin@mail.ru", NickName = name };
                IdentityResult result = userManager.Create(user, password);
                result = userManager.SetLockoutEnabled(user.Id, false);
            }

            // Add user admin to Role Admin if not already added
            IList<string> rolesForUser = userManager.GetRoles(user.Id);
            CustomIdentityRole adminrole = roleManager.FindByName(rolenames.First());
            if (!rolesForUser.Contains(adminrole.Name))
            {
                IdentityResult result = userManager.AddToRole(user.Id, adminrole.Name);
            }         
        } 

这是我的控制器的测试代码:

public ActionResult Index()
    {
        using (var context = new PortalContext())
        {
           context.Database.Initialize(false);
        }
        return View();
    }

但问题是,当代码的执行到达某些IO操作(UserManager.Create,UserManager.FindByName和其他管理员的类似操作)时,应用程序将无限期挂起。 Seed方法在DropCreateDbAlways派生类中执行。

无论如何数据库构造正确,我可以在服务器资源管理器中看到它的模式,这意味着没有连接字符串相关的问题。

这里出了什么问题?提前致谢。

更新
注意到一些奇怪的事情:如果我在这里设置true值:

context.Database.Initialize(true);

一切正常。据说我不知道​​EF本身工作的任何重要细节。但为什么会这样呢?问题仍然存在。

1 个答案:

答案 0 :(得分:1)

您是否尝试从数据库初始化程序中进行种子设定?您不应该从控制器操作中调用Initialize(),除非在极少数情况下您有大量播种并希望控制它何时运行。您的上下文构造函数应该设置初始化程序:

static ApplicationDbContext()
{
   // Set the database intializer which is run once during application start
   // This seeds the database with admin user credentials and admin role
   Database.SetInitializer(new ApplicationDbInitializer());
}

public class ApplicationDbInitializer : CreateDatabaseIfNotExists<ApplicationDbContext>
{

     protected override void Seed(ApplicationDbContext context)
     {
         InitializeIdentityForEF(context);
         base.Seed(context);
     }

     public static void InitializeIdentityForEF(ApplicationDbContext db)
     {
        if (!db.Users.Any())
        {
            var roleStore = new RoleStore<IdentityRole>(db);
            var roleManager = new RoleManager<IdentityRole>(roleStore);
            var userStore = new UserStore<ApplicationUser>(db);
            var userManager = new UserManager<ApplicationUser>(userStore);

            // Add missing roles
            var role = roleManager.FindByName("Admin");
            if (role == null)
            {
                role = new IdentityRole("Admin");
                roleManager.Create(role);
            }
            ...

            // Create test users
            var user = userManager.FindByName("admin");
            if (user == null)
            {
                 var newUser = new ApplicationUser()
                 {
                      UserName = "admin",
                      FirstName = "Admin",
                      LastName = "User",
                      Email = "xxx@xxx.net",
                      PhoneNumber = "5551234567",
                      MustChangePassword = false
                 };
                 userManager.Create(newUser, "Password1");
                 userManager.SetLockoutEnabled(newUser.Id, false);
                 userManager.AddToRole(newUser.Id, "Admin");
             }
             ...

请参阅http://www.codeguru.com/csharp/article.php/c19999/Understanding-Database-Initializers-in-Entity-Framework-Code-First.htm