c# – 允许最终用户在运行时切换Entity Framework提供程序

前端之家收集整理的这篇文章主要介绍了c# – 允许最终用户在运行时切换Entity Framework提供程序前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
考虑到我已使用.NET Core Web应用程序配置EF:
  1. services.AddDbContext<ApplicationDbContext>(options =>
  2. options.UsesqlServer(...));

我也可以下载一个包来支持例如sqlite:

  1. services.AddDbContext<ApplicationDbContext>(options =>
  2. options.Usesqlite(...));

我们如何允许用户在应用安装上“选择”提供商?我的意思是 – 例如,在wordpress中,您可以从下拉列表中进行选择.

这在.NET Core中是否可行?我看到的唯一方法是仅重启应用程序…

解决方法

这是一个关于如何实现DbContextFactory或DbContextProxy< T>的示例.这将创建正确的提供程序并返回它.
  1. public interface IDbContextFactory
  2. {
  3. ApplicationContext Create();
  4. }
  5.  
  6. public class DbContextFactory() : IDbContextFactory,IDisposable
  7. {
  8. private ApplicationContext context;
  9. private bool disposing;
  10.  
  11. public DbContextFactory()
  12. {
  13. }
  14.  
  15. public ApplicationContext Create()
  16. {
  17. if(this.context==null)
  18. {
  19. // Get this value from some configuration
  20. string providerType = ...;
  21. // and the connection string for the database
  22. string connectionString = ...;
  23.  
  24. var dbContextBuilder = new DbContextOptionsBuilder();
  25. if(providerType == "MSsql")
  26. {
  27. dbContextBuilder.UsesqlServer(connectionString);
  28. }
  29. else if(providerType == "sqlite")
  30. {
  31. dbContextBuilder.Usesqlite(connectionString);
  32. }
  33. else
  34. {
  35. throw new InvalidOperationException("Invalid providerType");
  36. }
  37.  
  38. this.context = new ApplicationContext(dbContextBuilder);
  39. }
  40.  
  41. return this.context;
  42. }
  43.  
  44. public void Dispose(){
  45. Dispose(true);
  46. GC.SuppressFinalize(this);
  47. }
  48.  
  49. protected virtual void Dispose(bool disposing){
  50. if (disposing){
  51. disposing?.Dispose();
  52. }
  53. }
  54. }

还要确保如上所示实现一次性模式,以便在工厂处置后立即处理上下文,以防止DbContext在内存中保留的时间超过必要时间并尽快释放非托管资源.

最后将工厂注册为作用域,就像上下文本身一样:

  1. services.AddScopedd<IDbContextFactory,DbContextFactory>();

更先进和通用/可扩展的方法是通过创建IDbContextProxy< T>.使用一些反射来获取正确的构造函数和DbContextOptionsBuilder的类.

也可以创建一个抽象提供者创建的IDbContextBuilder.

  1. public class sqlServerDbContextBuilder IDbContextBuilder
  2. {
  3. public bool CanHandle(string providerType) => providerType == "sqlServer";
  4.  
  5. public T CreateDbContext<T>(connectionString)
  6. {
  7. T context = ... // Create the context here
  8.  
  9. return context;
  10. }
  11. }

然后你可以选择没有硬编码if / else或switch块的正确提供者

  1. // Inject "IEnumerable<IDbContextBuilder> builders" via constructor
  2. var providerType = "sqlServer";
  3. var builder = builders.Where(builder => builder.CanHandle(providerType)).First();
  4. var context = builder.CreateDbContext<ApplicationContext>(connectionString);

添加新类型的提供程序就像添加依赖项和XxxDbContextBuilder类一样简单.

有关此方法和类似方法的更多信息,请参见here,herehere.

猜你在找的C#相关文章