As suggested by @Ivan Petrov, I search another location to throw the exception in the aim to handle it properly.
And I found it. Due to multi-tenant, I have a default schema definition for EF design time. So I can detect if we want to generate tables with default schema or not. And I can throw the exception at its location instead in Scope injection.
protected override void OnModelCreating(ModelBuilder builder)
{
if(!EF.IsDesignTime && Schema == DefaultSchema)
throw new ArgumentException("There is no data accessible");
...
}
I replace my code in Scope injection like this
//NOTICE: Scoped service for ClientDbContext resolution
builder.Services.AddScoped(sp =>
{
var configuration = sp.GetRequiredService<IConfiguration>();
var applicationDbContext = sp.GetRequiredService<ApplicationDbContext>();
var tenant = sp.GetRequiredService<ITenant>();
if (EF.IsDesignTime)
{
return new ClientDbContext(new DbContextOptions<ClientDbContext>(), configuration);
}
var client = applicationDbContext.Clients.FirstOrDefault(x => x.TenantId == tenant.TenantId);
return new ClientDbContext(configuration, client?.Schema ?? ClientDbContext.DefaultSchema);
});
With this code, I can handle it in controller and use the default exception handler.
Thanks for help