创建适当的数据库上下文 .NET Core 3

Creating a proper db context .NET Core 3

我正在尝试在 .NET Core 3 启动时显式创建数据库上下文

我知道我可以在 startup.cs ConfigureServices 中执行此操作以将 dbcontext 注入控制器(工作正常):

String dbconn = Configuration["ConnectionStrings:VerseDBConnectionStringMSSQL"];
services.AddDbContext<VerseDBContext>(options => options.UseSqlServer(dbconn));

但我试图概括存储提供程序(并使所有存储读取器的控制器代码保持相同),因此它需要一个 IVerseStorageReader 接口,而不是数据库上下文(因为我可能想从内存中读取,或 xmlfile 等)并在控制器中使用相同的代码,只需根据 appsettings 中的配置切换它。 VerseStorageReader 之一在构造函数中获取数据库上下文:

public class DBVerseReader : IVerseStorageReader
{
    private VerseDBContext _dbContext;
    public DBVerseReader(VerseDBContext dbContext)
    {
        _dbContext = dbContext;
    }
...
}

我的问题是:我无法完全弄清楚显式创建数据库上下文的正确语法。我非常接近(我认为)但这不起作用:

String dbconn = Configuration["ConnectionStrings:VerseDBConnectionStringMySQL"];
var optionsBuilder = new DbContextOptionsBuilder<VerseDBContext>();
optionsBuilder.UseMySql(dbconn);
VerseDBContext x = optionsBuilder.UseMySql<VerseDBContext>(dbconn); <-- compile error
services.AddSingleton<IVerseStorageReader>(new DBVerseReader(x));

有人可以告诉我我做错了什么吗?我要注入的是 IVerseStorageReader 的实例,而不是 DBContext。有 VerseStorageReader 的重载将 db 上下文作为输入,而其他重载则采用其他输入(例如 xmlfilename 等)...所以我想启动时添加一个 IVerseStorageReader 的实例并被注入(不是 dbcontext 注入).

您必须在配置后从构建器中获取选项

String dbconn = Configuration["ConnectionStrings:VerseDBConnectionStringMySQL"];
var optionsBuilder = new DbContextOptionsBuilder<VerseDBContext>();
optionsBuilder.UseMySql(dbconn);
DbContextOptions<VerseDBContext> options = optionsBuilder.Options;
VerseDBContext x = new VerseDBContext(options);
services.AddSingleton<IVerseStorageReader>(new DBVerseReader(x));

但是由于 DbContext 派生 类 通常被注册为作用域,我建议您将上下文移至工厂委托并将服务抽象也注册为作用域。

String dbconn = Configuration["ConnectionStrings:VerseDBConnectionStringMySQL"];
var optionsBuilder = new DbContextOptionsBuilder<VerseDBContext>();
optionsBuilder.UseMySql(dbconn);
DbContextOptions<VerseDBContext> options = optionsBuilder.Options;    
services.AddScoped<IVerseStorageReader>( sp => {
    VerseDBContext x = new VerseDBContext(options);
    return new DBVerseReader(x);
});