![](/img/trans.png)
[英]How to register RoleManager in Startup.cs in ASP.NET Core
[英]How to seed Users in ASP.NET 5 Startup.cs with Async
我正在嘗試在ASP.NET 5應用程序中創建一個初始的“超級用戶”。 使用MVC 6 / EF7的最新模板文件。
我可以按照這里列出的例子:
http://wildermuth.com/2015/3/17/A_Look_at_ASP_NET_5_Part_3_-_EF7
這很好 - 直到我嘗試執行異步方法。 例如:
await _userManager.CreateAsync(user, "P@55w0rd!");
甚至:
await _context.SaveChangesAsync();
同步方法可以正常工作,此代碼也可以在Startup.cs Configure{...}
之外執行。
我在申請開始時得到了“白色死亡之屏”。 我會在沒有異步的情況下完成所有操作,但我認為UserManager在Identity 3.0中沒有Create()
。
這是我不理解異步編程還是應該可行?
編輯 :添加了整個電話:
定義Seeder
類和創建用戶的方法:
public class Seeder
{
private ApplicationDbContext _context;
private UserManager<ApplicationUser> _userManager;
public Seeder(
ApplicationDbContext context,
UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
public async Task Seed()
{
await CreateUsersAsync();
}
public async Task CreateUsersAsync()
{
var user = await _userManager.FindByEmailAsync("superuser@superuser.com");
if (user == null)
{
var company = _context.Company.First(x => x.Name == "Acme Ltd");
user = new ApplicationUser
{
UserName = "superuser@superuser.com",
Email = "superuser@superuser.com",
CreatedDate = DateTime.Now,
IsActive = true,
CompanyID = company.CompanyId
};
await _userManager.CreateAsync(user, "P@55w0rd!!");
}
}
}
配置服務:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<Seeder>();
...
}
叫它:
public async void Configure(Seeder seeder)
{
...
await seeder.Seed();
...
}
有趣的是; 它確實創建了用戶 - 它只是不會繼續。 所以它第二次執行user != null
並且執行正常。
我認為問題是因為簽名形成了死鎖
public async void Configure(Seeder seeder).
由於它返回void,因此等待的Task永遠不會返回給創建死鎖的調用者。 你能做到嗎:
public async Task Configure(Seeder seeder).
我還沒有開始使用MVC 6,:(所以我可能會遺漏一些東西。但這就是為什么會出現僵局。
編輯:
由於您無法更改Configure的簽名,因此請創建一個名為ConfigureAsync的方法,該方法返回Task類型。 現在用你的用戶管理器代碼按照慣例等待它並從Configure調用ConfigureAsync但等待它。
ConfigureAsync.ConfigureAwait(false).Wait()
ConfigureAwait(false)用於防止等待異步方法完成的潛在死鎖。
完整示例:
public void Configure(Seeder seeder)
{
//Edited due to typo/bad syntax.
ConfigureAsync(seeder).Wait();
}
public async Task ConfigureAsync(Seeder seeder)
{
//Now treat this like true async/await.
await seeder.Seed().ConfigureAwait(false);
}
如果你在這里遇到死鎖,也許你的播種機應該是同步的? 我會避免在ASP.NET上下文中使用Task.Run(),因為這將首先通過占用兩個請求線程來完全打敗async / await的目的,如果同步完成,那么這兩個請求線程就完成了。
有時,您需要實現同步接口,但您只能使用異步API。 沒有完美的解決方案。
幸運的是,此代碼僅被調用一次,因此性能問題無關緊要。 您可以通過異步橋進行臟同步:
public void ConfigureServices(IServiceCollection services)
{
ConfigureServicesImpl(services).Wait(); //bridge
}
public async Task ConfigureServicesImpl(IServiceCollection services)
{
await ...;
}
您可能需要插入死鎖保護,例如ConfigureAwait(false)
或Task.Run(() => ...).Wait()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.