【问题标题】:Error WebHostBuilder allows creation only of a single instance of WebHost错误 WebHostBuilder 只允许创建单个 WebHost 实例
【发布时间】:2018-06-27 06:59:35
【问题描述】:

从 .NET Core 2.0 升级到 .NET Core 2.1

错误 WebHostBuilder 只允许创建单个 WebHost 实例


程序.cs

namespace WebApp1
{
    public class Program
    {
        public static void Main(string[] args)
        {

            CreateWebHostBuilder(args)
                .MigrateDbContext<ApplicationDbContext>((context, services) =>
                {
                    var env = services.GetService<IHostingEnvironment>();
                    var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();

                    new ApplicationDbContextSeed()
                        .SeedAsync(context, env, logger)
                        .Wait();
                }).Build().Run();
        }
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseStartup<Startup>()
                .ConfigureAppConfiguration((builderContext, config) =>
                {
                    config.AddEnvironmentVariables();
                });
    }
}

IWebHostExtensions.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;

namespace Microsoft.AspNetCore.Hosting
{
    public static class IWebHostExtensions
    {
        public static IWebHostBuilder MigrateDbContext<TContext>(this IWebHostBuilder webHost, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
        {
            using (var scope = webHost.Build().Services.CreateScope())
            {
                var services = scope.ServiceProvider;

                var logger = services.GetRequiredService<ILogger<TContext>>();

                var context = services.GetService<TContext>();

                try
                {
                    logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");

                    context.Database
                        .Migrate();

                    seeder(context, services);

                    logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
                }
            }

            return webHost;
        }
    }
}

学分:

https://github.com/dotnet-architecture/eShopOnContainers/blob/c83c6842f593aaaae59adefa78a412a4a6c87faa/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs

https://github.com/dotnet-architecture/eShopOnContainers/blob/a9676b4b5667eeebe0aa8ff5f64c604e9bd3971a/src/Services/Identity/Identity.API/Program.cs

https://github.com/dotnet-architecture/eShopOnContainers/blob/a9676b4b5667eeebe0aa8ff5f64c604e9bd3971a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs

【问题讨论】:

  • 您正在构建 WebHost 实例两次 - 在扩展方法中和在 Main() 中。这可能就是错误告诉您的内容。

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


【解决方案1】:

您在构建器上不止一次调用.Build()

扩展名中的第一个

public static class IWebHostExtensions
{
    public static IWebHostBuilder MigrateDbContext<TContext>(this IWebHostBuilder webHost, Action<TContext, IServiceProvider> seeder) where TContext : DbContext
    {
        using (var scope = webHost.Build().Services.CreateScope()) //<-- HERE
        {
            //...

又在Main

CreateWebHostBuilder(args)
    .MigrateDbContext<ApplicationDbContext>((context, services) =>
    {
        var env = services.GetService<IHostingEnvironment>();
        var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();

        new ApplicationDbContextSeed()
            .SeedAsync(context, env, logger)
            .Wait();
    }).Build().Run(); //<-- HERE

链接的示例使用主机而不是构建器来执行迁移。

重构您的扩展,类似于链接示例的扩展

public static class IWebHostExtensions {
    public static IWebHost MigrateDbContext<TContext>(this IWebHost webHost, Action<TContext, IServiceProvider> seeder) 
        where TContext : DbContext {
        using (var scope = webHost.Services.CreateScope()) {
            var services = scope.ServiceProvider;
            var logger = services.GetRequiredService<ILogger<TContext>>();
            var context = services.GetService<TContext>();

            try {
                logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");

                context.Database
                    .Migrate();

                seeder(context, services);

                logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
            } catch (Exception ex) {
                logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
            }
        }
        return webHost;
    }
}

并在 web 主机已经构建后调用它。

public class Program {
    public static void Main(string[] args) {

        BuildWebHost(args)
            .MigrateDbContext<ApplicationDbContext>((context, services) => {
                var env = services.GetService<IHostingEnvironment>();
                var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();

                new ApplicationDbContextSeed()
                    .SeedAsync(context, env, logger)
                    .Wait();
            })
            .Run();
    }
    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .ConfigureAppConfiguration((builderContext, config) => {
                config.AddEnvironmentVariables();
            })
            .Build();
}

【讨论】:

    猜你喜欢
    • 2017-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2016-07-26
    • 2020-05-09
    相关资源
    最近更新 更多