我正在尝试在ConfigureServices
方法之后添加Identity。这是因为我已经在ConfigureServices
方法之外注册了dbContext
。因此,现在我必须在配置dbContext
之后配置Identity(同样,这是我在ConfigureServices
之外完成的(。我为dbContext
所做的是创建了一个工厂,并将其添加到ConfigureServices
:
services.AddScoped<IDbContextFactory, DbContextFactory>();
然后我使用DI将其注入控制器的构造函数:
private IDbContextFactory contextFactory;
private AppDbContext context;
public DbTestController(IDbContextFactory _contextFactory)
{
contextFactory = _contextFactory;
context = contextFactory.Create(); //Create() returns an `AppDbContext`
}
我可以对数据库执行CRUD操作,但Identity不起作用,它抛出异常:
No service for type Microsoft.AspNetCore.Identity.XXX has been registered
这是因为我在ConfigureServices
中注册Identity,而没有首先设置dbContext
(因为它是在ConfigureServices
方法之后设置的。
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
有没有一种方法可以像我设置dbContext一样设置标识?
编辑:DbContextFactory
包括一个返回AppDbContext
的Create
方法。它从一些配置文件中读取用户对数据库提供程序的选择,相应地注册该提供程序,然后返回AppDbContext
。以下是Create
方法的代码:
public AppDbContext Create()
{
//Get this value from some configuration
string providerType = _configuration.GetValue<string>("DatabaseProvider");
//and the connection string for the database
string connectionString = _configuration.GetConnectionString(providerType);
var dbContextBuilder = new DbContextOptionsBuilder();
//Add some if else blocks here to check which provider to use
//and then call dbContextBuilder.UseABC(connectionString)
if (providerType == "MSSQL")
dbContextBuilder.UseSqlServer(connectionString);
else if (providerType == "SQLite")
dbContextBuilder.UseSqlite(connectionString);
//Create the context
context = new AppDbContext(dbContextBuilder);
return context;
}
该方法读取CCD_ 17&CCD_ 18从CCD_。这就是这个部分的样子:
"DatabaseProvider": "MSSQL", //could be MySQL, SQLite etc etc
"ConnectionStrings": {
"MSSQL": "Server=(localdb)\MSSQLLocalDB;Database=XXX_db;Trusted_Connection=True;MultipleActiveResultSets=true",
"SQLite": "Data Source=XXX_db.db"
}
像往常一样在ConfigureServices
中注册上下文和标识,在启动时在组合根中应用所需的逻辑。
//Get this value from some configuration
string providerType = Configuration.GetValue<string>("DatabaseProvider");
//and the connection string for the database
string connectionString = Configuration.GetConnectionString(providerType);
services.AddDbContext<AppDbContext>(options => {
if (providerType == "MSSQL")
options.UseSqlServer(connectionString);
else if (providerType == "SQLite")
options.UseSqlite(connectionString);
});
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
你需要做的是重新设计工厂
public class DbContextFactory : IDbContextFactory {
private readonly Func<AppDbContext> factory;
public DbContextFactory(Func<AppDbContext> factory) {
this.factory = factory;
}
public AppDbContext Create() {
return factory();
}
}
并相应地向工厂代表注册
services.AddScoped<IDbContextFactory, DbContextFactory>(sp =>
new DbContextFactory(() => sp.GetRequiredService<AppDbContext>()));