【发布时间】:2021-05-11 13:42:52
【问题描述】:
我有一个有效的 EFCore、.NET5、Blazor WASM 应用程序。
我在Program.Main() 中调用await host.MigrateDatabase(); 以使我的数据库始终保持最新状态。
public static async Task<IHost> MigrateDatabase(this IHost host)
{
using var scope = host.Services.CreateScope();
try
{
// Get the needed context factory using DI:
var contextFactory = scope.ServiceProvider.GetRequiredService<IDbContextFactory<AppDbContext>>();
// Create the context from the factory:
await using var context = contextFactory.CreateDbContext();
// Migrate the database:
await context.Database.MigrateAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
return host;
}
在我的AppDbContext 中,我已覆盖SaveChangesAsync() 以添加和更新CreatedOn 和UpdatedOn。
我之前在DbContext.SaveChanges overrides behaves unexpected 中提到过这一点。
我还想用 userId 填写 CreatedBy 和 UpdatedBy。
我有一个IdentityOptions 类来保存用户数据:
public class IdentityOptions
{
public string UserId => User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
public ClaimsPrincipal User { get; set; }
}
我已经像这样在 StartUp 中注册了这个类:
services.AddScoped(sp =>
{
var context = sp.GetService<IHttpContextAccessor>()?.HttpContext;
var identityOptions = new IdentityOptions();
if (context?.User.Identity != null && context.User.Identity.IsAuthenticated)
{
identityOptions.User = context.User;
}
return identityOptions;
});
我将这个IdentityOptions 类注入到其他几个服务中,没有任何问题。
但是当我将它注入我的AppDbContext:
public AppDbContext(DbContextOptions<AppDbContext> options, IdentityOptions identityOptions)
: base(options)
{
...
}
MigrateDatabase() 出现错误:"Cannot resolve scoped service 'IdentityOptions' from root provider."
我尝试了很多在谷歌上搜索到的选项,但找不到适合我的解决方案。 请指教。
更新:
services.AddDbContextFactory<AppDbContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection"),
b => b.MigrationsAssembly("DataAccess"))
#if DEBUG
.LogTo(Console.WriteLine, new [] {RelationalEventId.CommandExecuted})
.EnableSensitiveDataLogging()
#endif
);
【问题讨论】:
-
你是如何注册数据库上下文工厂的?
AddDbContextFactory?寿命? (默认为单例)。 -
感谢伊万的回复。我已经更新了我的问题。我用
AddDbContextFactory -
您是否尝试过传递不同的生命周期,例如
Scoped(AddDbContextFactory的最后一个可选参数)?我不是 DI 专家,但将作用域注入单例听起来有问题(逻辑上)。让我知道这是否有帮助,否则您可能需要自己的IDbContextFactory<>实现。但让我们先看看这个。 -
是的,伊万。添加
lifetime: ServiceLifetime.Scoped解决了我的问题。您可以将其发布为答案吗?我会接受的。 -
很高兴它帮助了交配。但正如我所说,我离 DI 还很远,所以请随时发布并接受一个自我回答(供未来的读者使用),我很乐意对其进行 UV 处理。
标签: asp.net-core dependency-injection entity-framework-core dbcontext