我写了一个类来为数据库添加数据。调试时,它会堆叠在等待状态IdentitySeedData.EnsurePopulated(service);问题可能出在usermanager.createasync()上。看看:
namespace SportStore1
{
public class Program
{
public static void Main(string[] args)
{
var Host = BuildWebHost(args);
var Scopes = Host.Services.GetRequiredService<IServiceScopeFactory>();
using (var scope = Scopes.CreateScope())
{
var service = scope.ServiceProvider;
SeedDataFunc(service);
SeedIdentityDataFunc(service);
}
Host.Run();
}
public static void SeedDataFunc(IServiceProvider service)
{
SeedData.EnsurePopulated(service);
}
public static async void SeedIdentityDataFunc(IServiceProvider service)
{
await IdentitySeedData.EnsurePopulated(service);
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
/*
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
*/
}
}
namespace SportStore1.Data
{
public static class IdentitySeedData
{
public static async Task EnsurePopulated(IServiceProvider service)
{
UserManager<IdentityUser> userManager = service.GetRequiredService<UserManager<IdentityUser>>();
IConfiguration configuration = service.GetRequiredService<IConfiguration>();
ApplicationDbContext dbContext = service.GetRequiredService<ApplicationDbContext>();
if (!dbContext.Roles.Any())
{
foreach (var role in Roles)
{
dbContext.Add(role);
await dbContext.SaveChangesAsync();
}
}
if (!dbContext.Users.Any())
{
var user = new IdentityUser() { UserName = configuration["Email"], Email = configuration["Email"], EmailConfirmed = true };
await userManager.CreateAsync(user, configuration["Password"]);
}
if (!dbContext.UserRoles.Any())
{
var roleID = dbContext.Roles.Where(p => p.Name == "Administrator").FirstOrDefault().Id;
var userID = dbContext.Users.Where(p => p.Email == configuration["Email"]).FirstOrDefault().Id;
var userRole = new IdentityUserRole<string>()
{
RoleId = roleID,
UserId = userID
};
dbContext.UserRoles.Add(userRole);
await dbContext.SaveChangesAsync();
}
}
private static List<IdentityRole> Roles = new List<IdentityRole>()
{
new IdentityRole { Name = "Administrator", NormalizedName = "Administrator", ConcurrencyStamp = Guid.NewGuid().ToString() },
new IdentityRole { Name = "Manager", NormalizedName = "Manager", ConcurrencyStamp = Guid.NewGuid().ToString() },
new IdentityRole { Name = "User", NormalizedName = "User", ConcurrencyStamp = Guid.NewGuid().ToString()}
};
}
}
它在等待IdentitySEedData.EnsurePopulated(service)时堆叠,并显示消息System.ObjectDisposedException:'无法访问已处置的对象。 对象名称:“ UserManager`1”。有解决办法吗?
答案 0 :(得分:0)
您需要等待异步方法。看来Main
是同步的,但是您可以更改它。在C#7.2+中,您实际上只能拥有一个异步main:
public static async Task Main(string[] args)
在较小的版本中,您只需这样做:
public static void Main(string[] args) =>
MainAsync(args).GetAwaiter().GetResult();
public static async Task MainAsync(string[] args)
{
...
}
无论如何,当您使用异步Main时,编译器只是在幕后为您构建。请记住,如果要这样做,您还需要做await host.RunAsync();
。
也就是说,这不再是数据库播种的方法。参见documentation。
答案 1 :(得分:0)
您还需要使用using()
语句来确保dbcontext一旦超出范围就被处置。
我在使用ApplicationUser
的全新asp.net core 2.0个人用户帐户中尝试了您的代码,并且在使用using
块后效果很好:
public static class IdentitySeedData
{
public static async Task EnsurePopulated(IServiceProvider service)
{
UserManager<ApplicationUser> userManager = service.GetRequiredService<UserManager<ApplicationUser>>();
IConfiguration configuration = service.GetRequiredService<IConfiguration>();
using (var dbContext = service.GetRequiredService<ApplicationDbContext>())
{
//ApplicationDbContext dbContext = service.GetRequiredService<ApplicationDbContext>();
if (!dbContext.Roles.Any())
{
foreach (var role in Roles)
{
dbContext.Add(role);
await dbContext.SaveChangesAsync();
}
}
if (!dbContext.Users.Any())
{
var user = new ApplicationUser() { UserName = configuration["Email"], Email = configuration["Email"], EmailConfirmed = true };
await userManager.CreateAsync(user, configuration["Password"]);
}
if (!dbContext.UserRoles.Any())
{
var roleID = dbContext.Roles.Where(p => p.Name == "Administrator").FirstOrDefault().Id;
var userID = dbContext.Users.Where(p => p.Email == configuration["Email"]).FirstOrDefault().Id;
var userRole = new IdentityUserRole<string>()
{
RoleId = roleID,
UserId = userID
};
dbContext.UserRoles.Add(userRole);
await dbContext.SaveChangesAsync();
}
}
}
private static List<IdentityRole> Roles = new List<IdentityRole>()
{
new IdentityRole { Name = "Administrator", NormalizedName = "Administrator", ConcurrencyStamp = Guid.NewGuid().ToString() },
new IdentityRole { Name = "Manager", NormalizedName = "Manager", ConcurrencyStamp = Guid.NewGuid().ToString() },
new IdentityRole { Name = "User", NormalizedName = "User", ConcurrencyStamp = Guid.NewGuid().ToString()}
};
}
启动:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
}
请参阅Cannot access a disposed object in ASP.NET Core when injecting DbContext