我有一个ASP.NET MVC 5项目(razor引擎),它具有带有个人用户帐户的Identity 2.0。我正在使用Visual Studio Professional 2013
我没有找到任何明确的例子(为什么它没有开箱即用?)我如何为Identity 2.0数据库播种,我看到的所有例子都有一半支持,因为他们不会说你必须在哪里实现它。
我使用了enable-migrations,它创建了一个带有Configuration.cs文件的Migrations文件夹。它有一个Seed方法覆盖,但是当我放置一个断点时,它注意到它永远不会被执行,实际上Identity数据库甚至没有用模式填充。
那么我必须做什么,以及第一次在数据库上创建Identity 2.0模式(连接字符串是否正确并且存在空数据库)。我如何装配种子?
在IdentityModels.cs上我有这个: public class ApplicationDbContext:IdentityDbContext { ublic ApplicationDbContext():base(" DefaultConnection",throwIfV1Schema:false) {}
public static ApplicationDbContext Create() {
return new ApplicationDbContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
// to avoid the "has no keys" errors when running Update-Database on PM
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id).ToTable("AspNetRoles");
modelBuilder.Entity<IdentityUser>().ToTable("AspNetUsers");
modelBuilder.Entity<IdentityUserLogin>().HasKey(l => new { l.UserId, l.LoginProvider, l.ProviderKey }).ToTable("AspNetUserLogins");
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId }).ToTable("AspNetUserRoles");
modelBuilder.Entity<IdentityUserClaim>().ToTable("AspNetUserClaims");
}
}
在Migrations / Configuration.cs中(由PM&gt; Enable-Migrations添加)我有:
internal sealed class Configuration : DbMigrationsConfiguration<Models.ApplicationDbContext> {
public Configuration() {
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Models.ApplicationDbContext context) {
WriteReferenceData();
}
}
在Application_Start()方法的Global.asax.cs文件中,我添加了这个:
System.Data.Entity.Database.SetInitializer<Models.ApplicationDbContext>(new System.Data.Entity.MigrateDatabaseToLatestVersion<Models.ApplicationDbContext, Migrations.Configuration>());
在IdentityConfig.cs中我也有这个DB Initializer,虽然它似乎是孤儿,因为我不知道在哪里插入它:
public class ApplicationDbInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<Models.ApplicationDbContext> {
protected override void Seed(ApplicationDbContext context) {
WriteReferenceData();
base.Seed(context);
}
}
最后,WriteReferenceData方法在其他类中或多或少地执行此操作:
System.Data.Entity.DbContextTransaction transaction = null;
try {
System.Data.Entity.DbContext ctx = Models.ApplicationDbContext.Create();
transaction = ctx.Database.BeginTransaction();
CreateRoles(ctx);
CreateUsers(ctx);
CreateRoleAssociations(ctx);
ctx.SaveChanges();
transaction.Commit();
succeeded = true;
}
catch (Exception ex) {
if (transaction != null { transaction.Rollback(); transaction.Dispose(); }
succeeed = false;
}
return succeeded;
答案 0 :(得分:15)
EF有two different Seed methods。一个用于数据库初始化程序,另一个用于迁移。由于您已启用迁移,我将在此处描述如何使用迁移种子方法...
首先,即使您启用了迁移,默认情况下EF仍然使用CreateDatabaseIfNotExists
数据库初始化程序。这意味着当您运行应用程序时,第一次访问ApplicationDbContext
时,将调用初始化程序,如果表已经不存在,它将从Code First映射创建数据库表。您没有看到创建的模式,因为您可能没有访问过数据库上下文。在新的Web应用程序中,通常在您第一次注册用户或尝试登录时触发。
要为ASP.NET标识表提供种子,您需要做两件事。第一种是将种子逻辑添加到Configuration.cs
中的种子方法中。第二种是通过在程序包管理器控制台中运行它或使用update-database
数据库初始化程序来触发MigrateDatabaseToLatestVersion
...
以下是您可以在Seed方法中创建角色和用户的示例...
public Configuration()
{
AutomaticMigrationsEnabled = true;
// ...
}
protected override void Seed(MyProject.Web.Models.ApplicationDbContext context)
{
if (!context.Roles.Any())
{
var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var role = new IdentityRole{
Name = "Administrator"
};
roleManager.Create(role);
}
if (!context.Users.Any())
{
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new ApplicationUserManager(userStore);
var user = new ApplicationUser {
Email = "foo@bar.com",
UserName = "SuperUser"
};
userManager.Create(user, "MySecretPassword1234");
userManager.AddToRole(user.Id, "Administrator");
}
}
完成此操作后,您可以从程序包管理器控制台运行Update-Database
以将数据库迁移到最新架构并运行Seed方法。
或者您可以通过修改MigrateDatabaseToLatestVersion
中的上下文来更改EF以使用IdentityModels.cs
初始化程序...
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer<ApplicationDbContext>(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
}
}
现在,当您运行应用程序时,第一次使用数据库上下文时,它将运行update-database
并播种它。
答案 1 :(得分:3)
我认为我可以解决为什么从不触发Seed的问题:因为仅在应用程序尝试连接数据库时调用Seed,而不是在应用程序启动时调用。
我创建了一些示例,我已成功使用您的代码,无论是否迁移。但是,由于您希望在启用迁移时使用它,下面是示例代码。
非常重要:要在Seed中实际查看断点,请运行应用程序,按Login并使用种子功能中的凭据来访问应用程序。如果您收到“用户名或密码无效”,请注意manager.PasswordValidator
IdentityConfig.cs :: Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context).
媒体资源
在VS2013中创建一个新的ASP.NET MVC 5项目
使用Update-Package命令更新所有软件包。
启用-迁移
在迁移创建的Configuration.cs中添加以下代码:
internal sealed class Configuration : DbMigrationsConfiguration
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(ApplicationDbContext context)
{
bool itWorks = WriteReferenceData(context);
base.Seed(context);
}
private bool WriteReferenceData(ApplicationDbContext ctx)
{
DbContextTransaction transaction = null;
bool succeeded = false;
try
{
transaction = ctx.Database.BeginTransaction();
CreateRoles(ctx);
CreateUsers(ctx);
ctx.SaveChanges();
transaction.Commit();
succeeded = true;
}
catch (Exception ex)
{
if (transaction != null) { transaction.Rollback(); transaction.Dispose(); }
succeeded = false;
}
return succeeded;
}
private void CreateRoles(ApplicationDbContext ctx)
{
// Out of the box
// ctx.Roles.AddOrUpdate(
// new IdentityRole { Name = "Administrator" },
// new IdentityRole { Name = "Guest" }
// );
// Another approach
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(ctx));
var roleName = "Administrator";
//Create role if it does not exist
if (!RoleManager.RoleExists(roleName))
{
var roleresult = RoleManager.Create(new IdentityRole(roleName));
}
}
private void CreateUsers(ApplicationDbContext ctx)
{
// Out of the box approach
// ctx.Users.AddOrUpdate(
// new ApplicationUser { Email = "foo@xyz.com", UserName = "foo@xyz.com" }
// );
// Another approach
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(ctx));
var user = new ApplicationUser() { UserName = "foo@xyz.com", Email="foo@xyz.com"};
var password = "Wh@tever777";
var adminresult = UserManager.Create(user, password);
//Add User Admin to Role Administrator
if (adminresult.Succeeded)
{
var result = UserManager.AddToRole(user.Id, "Administrator");
}
}
}
在Global.asax.cs :: Application_Start()中,添加以下行:
Database.SetInitializer<ApplicationDbContext>(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
运行!
如果您还需要禁用迁移的代码示例,请与我们联系。
答案 2 :(得分:2)
所以我们通过以下方式在我们的示例包中做类似的事情(使用我们的管理员用户播种数据库)
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
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<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
// This is useful if you do not want to tear down the database each time you run the application.
// public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
// This example shows you how to create a new database if the Model changes
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context) {
DoYourSeedingHere(context);
base.Seed(context);
}
}
答案 3 :(得分:1)
要完成此问题..正如Corneliu Serediuc所说,您只需尝试在应用程序启动期间连接到数据库,例如,像这样(IdentityModel.cs):
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
var ctx = new ApplicationDbContext();
var runSeed = ctx.Roles.AnyAsync();
return ctx;
}
} 顺便说一句,Corneliu感谢你的代码示例,他们帮了我很多。
答案 4 :(得分:0)
如果您想使用CSV批量插入新帐户,可以使用此项目:https://github.com/Stonefinch/AspNetUserMaintenanceAzureSiteExtension
它也可以作为Azure站点扩展安装:https://www.siteextensions.net/packages/AspNetUserMaintenanceAzureSiteExtension/