私は現在、ベン・フォスターズとSaaskitと仲良くしています。データをシードする際にAppTenantがnullになるのはなぜですか?
私はAppTenantIdプロパティでApplicationUser
を拡張し、ユーザーを識別するためにAppTenantを使用するカスタムUSERSTOREを作成しました:
public class TenantEnabledUserStore : IUserStore<ApplicationUser>, IUserLoginStore<ApplicationUser>,
IUserPasswordStore<ApplicationUser>, IUserSecurityStampStore<ApplicationUser>
{
private bool _disposed;
private AppTenant _tenant;
private readonly ApplicationDbContext _context;
public TenantEnabledUserStore(ApplicationDbContext context, AppTenant tenant)
{
_context = context;
_tenant = tenant;
}
/*... implementation omitted for brevity*/
}
ユーザー登録やログの場合、これは正常に動作します。 AppTenant
が正しく設定されています。 SeedData.Initialize(app.ApplicationServices);
が私のStatup.Configure()
メソッドの最後に呼び出されたときに問題が発生します。
public static class SeedData
{
public async static void Initialize(IServiceProvider provider)
{
using (var context = new ApplicationDbContext(
provider.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
{
var admin = new ApplicationUser
{
AppTenantId = 1,
Email = "[email protected]",
UserName = "Administrator",
EmailConfirmed = true
};
if(!context.Users.Any(u => u.Email == admin.Email))
{
var userManager = provider.GetRequiredService<UserManager<ApplicationUser>>();
await userManager.CreateAsync(admin, "Penis123#");
}
context.SaveChanges();
}
}
}
たUserManagerカスタムUSERSTOREを呼び出すことが、今AppTenantはnullですされています。 AppTenantは、上記USERSTOREのコンストラクタにヌルとして渡されるので、私は、System.InvalidoperationException
に直面しています
public Task<ApplicationUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
return _context.Users.FirstOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName && u.AppTenantId == _tenant.AppTenantId, cancellationToken);
}
コードが最終的に到達したとき。
私は間違っていますか?間違ったやり方をしているのですか?
更新:は 今の私はバール・アプローチをとっている、のUserManagerを回避し、モックAppTenantとUSERSTOREの私自身のインスタンスを作成:
if (!context.Users.Any(u => u.Email == admin.Email))
{
var userStore = new TenantEnabledUserStore(context, new AppTenant
{
AppTenantId = 1
});
await userStore.SetPasswordHashAsync(admin, new PasswordHasher<ApplicationUser>().HashPassword(admin, "VeryStrongPassword123#"), default(CancellationToken));
await userStore.SetSecurityStampAsync(admin, Guid.NewGuid().ToString("D"), default(CancellationToken));
await userStore.CreateAsync(admin, default(CancellationToken));
}
Nonthelessを、私はまだに興味よりクリーンなアプローチ、それはハッキーを感じない。
は、シードされるデータのテナント部分ですか?すなわち、最初のテナントが存在するために播種が行われなければならないか? –
これはうまくいかないでしょう。この例では、 'new'キーワードを使って手動で' ApplicationDbContext'をインスタンス化します。しかし、次の行では 'ApplicationDbContext'に依存する' UserManager 'を解決します。ユーザ管理は 'ApplicationDbContext'の別のインスタンスを受け取ります。' user'はまだ作成されていません( 'SaveChanges'メソッドは' CreateAsync'の後に呼び出されるため) –
Tseng
あなたは'ApplicationDbContext'をIoCコンテナから解決する必要がありますしかし、注意する必要があります。アプリ起動時にこれを行うとき。シングルトンを作成するApplicationServices(アプリケーションの起動時にリクエストはありません)。まずスコープを作成し、スコープから解決し、スコープを最後に配置する必要があります。 – Tseng