【问题标题】:ASP.NET Core 2 + Get instance of db contextASP.NET Core 2 + 获取数据库上下文实例
【发布时间】:2018-02-03 17:13:25
【问题描述】:

我正在尝试获取 DbContext 的实例(因此我可以在启动时做一些额外的工作),尝试在 Configure 方法中获取实例时出现以下错误:

System.InvalidOperationException: '无法从根提供者解析范围服务'MyApp.Data.MyDbContext'。'

public void ConfigureServices(IServiceCollection services)
{
 services.AddDbContext<MyDbContext>(
                options => options.UseSqlServer(Configuration.GetConnectionString("MyDbContext")));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    var dbContext = app.ApplicationServices.GetService(typeof(MyDbContext)) as MyDbContext;
}

我可以通过控制器等访问 DbContext 的实例

【问题讨论】:

  • 您可以将依赖项添加到 Configure 方法中,它们将自动得到解决。尝试将签名更改为 public void Configure(IApplicationBuilder app, IHostingEnvironment env, MyDbContext dbContext)

标签: c# asp.net-core entity-framework-core


【解决方案1】:

Paul Hiles 的评论是正确的,但该方法在 .NET Core 1.0 中效果更好。

在 ASP.NET Core 2.0 中,在 Startup.cs 中运行任何数据库设置通常不是一个好主意。这是因为如果您从 CLI 或 Visual Studio 运行任何迁移,它将运行所有 Startup.cs 并尝试运行将失败的配置。当然,如果您不使用 Entity-Framework,那么这不是问题,但它仍然不是 2.0 中推荐的方式。现在建议在Program.cs 中进行。

例如,您可以创建IWebHost 的扩展方法,它将运行您需要的任何设置。

public static IWebHost MigrateDatabase(this IWebHost webHost)
{
    var serviceScopeFactory = (IServiceScopeFactory)webHost.Services.GetService(typeof(IServiceScopeFactory));

    using (var scope = serviceScopeFactory.CreateScope())
    {
        var services = scope.ServiceProvider;
        var dbContext = services.GetRequiredService<YourDbContext>();

        dbContext.Database.Migrate();
    }

    return webHost;
}

然后在Program.cs 中,您可以在运行之前调用该方法。

public static void Main(string[] args)
{
    BuildWebHost(args)
        .MigrateDatabase()
        .Run();
}

【讨论】:

  • ...如果您将所有 DbContext 项目保存在单独的类库中?有没有办法为 Asp.Net Core 2 Web 应用程序设置它?
  • 只是向您发送评论,让您知道这对我在 Heroku 上使用 ASP.NET Core 有很大帮助。我无法运行“heroku run dotnet ef database update”,但我能够使用此代码让它在我推送到 heroku master 后启动时运行迁移。我将它包装在一个环境变量中(检查是否等于“true”),以便我可以控制它是否运行,以防万一我需要。与 Heroku 的 Web 仪表板配合得很好。
  • 当它不回答问题时,这是如何被接受的答案?我很困惑。
【解决方案2】:

Core 2.1 以后的更新

只是为了补充@Travis Boatman 的出色答案,首选的Main 方法语法具有changed slightly from Core 2.1 onwards,默认Main 方法现在具有CreateWebHostBuilder 而不是BuildWebHost

调用扩展方法的修改代码如下所示。

注意:这里的顺序很重要,Build 方法返回一个WebHost,这是扩展方法正在扩展的,所以你需要在Build() 之后和Run() 之前调用 migrate 方法):

public static void Main(string[] args)
{
    CreateWebHostBuilder(args)
        .Build()
        .MigrateDatabase()
        .Run();
}

迁移多个 DbContext

我们的项目中有不止一个DbContext,所以我把扩展方法改成了可以接受任何类型DbContext的泛型方法:

public static IWebHost MigrateDatabase<T>(this IWebHost webHost) where T:DbContext
{
    var serviceScopeFactory = (IServiceScopeFactory)webHost
        .Services.GetService(typeof(IServiceScopeFactory));

    using (var scope = serviceScopeFactory.CreateScope())
    {
        var services = scope.ServiceProvider;

        var dbContext = services.GetRequiredService<T>();
        dbContext.Database.Migrate();
    }

    return webHost;
}

然后您可以链接调用以迁移不同的上下文:

CreateWebHostBuilder(args)
    .Build()
    .MigrateDatabase<ApiAuthDbContext>()
    .MigrateDatabase<MainDbContext>()
    .MigrateDatabase<SomeOtherDbContext>()
    .Run();

【讨论】:

  • CreateHostBuilder 显示错误“‘IHost’不包含‘MigrateDatabase’的定义,并且最佳扩展方法重载‘Extensions.MigrateDatabase(IWebHost)’需要‘IWebHost’类型的接收器”。跨度>
  • 找到解决方案,只需将 MigrateDatabase 方法“IWebHost”更改为“IHost”并添加“使用 Microsoft.Extensions.Hosting”即可。
猜你喜欢
  • 1970-01-01
  • 2016-08-31
  • 2018-04-05
  • 2021-06-29
  • 1970-01-01
  • 2018-02-23
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
相关资源
最近更新 更多