考虑到我已使用.NET Core Web应用程序配置EF:
- services.AddDbContext<ApplicationDbContext>(options =>
- options.UsesqlServer(...));
- services.AddDbContext<ApplicationDbContext>(options =>
- options.Usesqlite(...));
我们如何允许用户在应用安装上“选择”提供商?我的意思是 – 例如,在wordpress中,您可以从下拉列表中进行选择.
这在.NET Core中是否可行?我看到的唯一方法是仅重启应用程序…
解决方法
这是一个关于如何实现DbContextFactory或DbContextProxy< T>的示例.这将创建正确的提供程序并返回它.
- public interface IDbContextFactory
- {
- ApplicationContext Create();
- }
- public class DbContextFactory() : IDbContextFactory,IDisposable
- {
- private ApplicationContext context;
- private bool disposing;
- public DbContextFactory()
- {
- }
- public ApplicationContext Create()
- {
- if(this.context==null)
- {
- // Get this value from some configuration
- string providerType = ...;
- // and the connection string for the database
- string connectionString = ...;
- var dbContextBuilder = new DbContextOptionsBuilder();
- if(providerType == "MSsql")
- {
- dbContextBuilder.UsesqlServer(connectionString);
- }
- else if(providerType == "sqlite")
- {
- dbContextBuilder.Usesqlite(connectionString);
- }
- else
- {
- throw new InvalidOperationException("Invalid providerType");
- }
- this.context = new ApplicationContext(dbContextBuilder);
- }
- return this.context;
- }
- public void Dispose(){
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing){
- if (disposing){
- disposing?.Dispose();
- }
- }
- }
还要确保如上所示实现一次性模式,以便在工厂处置后立即处理上下文,以防止DbContext在内存中保留的时间超过必要时间并尽快释放非托管资源.
最后将工厂注册为作用域,就像上下文本身一样:
- services.AddScopedd<IDbContextFactory,DbContextFactory>();
更先进和通用/可扩展的方法是通过创建IDbContextProxy< T>.使用一些反射来获取正确的构造函数和DbContextOptionsBuilder的类.
也可以创建一个抽象提供者创建的IDbContextBuilder.
然后你可以选择没有硬编码if / else或switch块的正确提供者
- // Inject "IEnumerable<IDbContextBuilder> builders" via constructor
- var providerType = "sqlServer";
- var builder = builders.Where(builder => builder.CanHandle(providerType)).First();
- var context = builder.CreateDbContext<ApplicationContext>(connectionString);