当 dbContext 也作为服务注入时如何使用连接字符串设置它

How to set dbContext with a connection string when it is also injected as a service

我在 web-api 项目中使用 EF-Core,并使用 DI 机制将 DBContext 注入操作方法。 但是 - 另外 - 我想在服务器启动时使用 EF dbContext 访问数据库, 在启动方法中 - 这是非 http 上下文,意思是 - DBContext 尚未启动 - 它在 ConfigureServices 方法中启动,并且在 stratup 方法之后启动. 为了进一步解释,这是 Startup.cs 和相关流程的其余部分:

public class Startup
{
    public IConfiguration Configuration {get; }
    
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
        RepositoriesManager.Initiate(configuration);
        //In addition - I now would like to use it to initiate repository by using the EF Core dbContext
        //Another option is to run this methos after adding the dbContext serice - in the ConfigureServices
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.Add....
        services.AddDbContext<MyDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("myDB)));
        //Option to execute it here instead of in the Startup
        RepositoriesManager.Initiate(configuration);
    }
}

RepositoriesManager 是一个静态 class ,使用配置从外部获取数据 API

public static Class RepositoriesManager
{
    static RepositoriesManager(){} //static constructor
    
    public static void Initiate(IConfiguration configuration)
    {
        //to make a long story short:
        GetDataFromDBUsingEF();
    }

    //This method can be called also from action method (controller) - where the myDBContext is passed - this is not the case here
    public static GetDataFromDBUsingEF(MyDBContext myDBContext = null) 
    {
        if (myDBContext == null)
        {
            //one option - not working:
            
            var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
            var sp = serviceCollection.GetService<MyDBContext>();
            
            
            
            //second option - also not working:
            myDBContext = new MyDBContext(); // This should initiate the DBContext in some scenarios 
        }

    }
}

我正在尝试使用 dbContext OnConfiguration 方法:

protected override void OnConfiguration(DbContextOptionsBuilder optionsBuilder)  
{
   if (!optionsBuilder.IsConfigured)
   {
        IConfigurationRoot configuration = new ConfigurationBuilder().SetBasePath(AppDomain.CurrentDomain.BaseDirectory).AddJsonFile("appsettings.json").Build();
        optionsBuilder.UseSqqlServer(configuration.GetConnectionString("<connection string key>"));
   }
}

在每次 DbContext 启动时都应使用其构造函数调用此方法。 现在当我启动 dbContext 时还没有达到它。我认为原因是文档所声称的: “如果在此上下文的选项上明确设置模型(通过 Microsoft.EntityFrameworkCore.DbContextOptionsBuilder.UseModel(Microsoft.EntityFrameworkCore.Metadata.IModel)),则此方法将不会 运行” .

如何在未注入时获取 DBContext?

选项 1:通过 new

在启动构造函数中获取上下文
public Startup(IConfiguration configuration)
{
    Configuration = configuration;

    var contextOptions = new DbContextOptionsBuilder<MvcContext>()
        .UseSqlServer(Configuration.GetConnectionString("MvcContext"))
        .Options;

    using var context = new MvcContext(contextOptions);
    var configFromDb = context.MvcConfiguration.First();
}

选项 2:在 ConfigureServices 中调用 Configure 所需的选项并使用上下文(将在实际使用选项时调用)

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddDbContext<MvcContext>(options =>
    {
        options.UseSqlServer(Configuration.GetConnectionString("MvcContext"));
    });

    services.AddOptions<DbConfigOptions>().Configure<IServiceProvider>((options, sp) =>
    {
        using var scope = sp.CreateScope();
        using var dbContext = scope.ServiceProvider.GetRequiredService<MvcContext>();
        options.UseDeveloperExceptionPage = dbContext.MvcConfiguration.Single().UseDeveloperExceptionPage;
    });
}

选项3:当DBContext配置在ConfigureServices中时,可以在Startup.Configure中注入使用

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MvcContext dbContext)
{
    var configFromDb = dbContext.MvcConfiguration.Single();
    
    //...
}