无法在注册多个 DbContext 的项目中添加 EF Core 迁移

问题描述

我有一个包含两个 DbContext 的控制台应用程序。一个是使用 Masstransit 配置的,另一个是对我已经运行迁移的另一个项目的引用。因此,我想在此服务上为 Masstransit 配置的 DbContext 运行迁移,但收到以下错误消息:

“找到了多个 DbContext。指定使用哪一个。对 PowerShell 命令使用“-Context”参数,对 dotnet 命令使用“--context”参数。”

但是,当我使用“dotnet ef migrations add InitialCreate -c CourierServiceDbContext”指定上下文时,出现以下错误

“无法创建类型为“CourierServiceDbContext”的对象。有关设计时支持的不同模式,请参阅StatusOptions

明确地说,我只想为 Masstransit 配置的 DbContext、CourierServiceDbContext 而不是引用的 DbContext、OrdersDbContext 运行迁移。

static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder()
        .UseSerilog((host,log) =>
        {
            string? appBin = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            log.MinimumLevel.information();
            log.Writeto.File($"{appBin}/log/log-{DateTime.Now:yyMMdd_HHmmss}.txt");
            log.Writeto.Console(LogEventLevel.Debug);
        })
        .ConfigureAppConfiguration((host,builder) =>
        {
            builder.AddJsonFile("appsettings.json",false);
        })
        .ConfigureServices((host,services) =>
        {
            services.AddDbContext<OrdersDbContext>(x =>
                x.UseNpgsql(host.Configuration.GetConnectionString("OrdersConnection")));
            
            services.AddMasstransit(x =>
            {
                x.AddConsumer<CourierdispatchConsumer>();
                
                x.SetKebabCaseEndpointNameFormatter();
                
                x.UsingRabbitMq((context,cfg) =>
                {
                    string vhost = host.Configuration
                        .GetSection("Application")
                        .GetValue<string>("VirtualHost");
                    
                    cfg.Host("localhost",vhost,h =>
                    {
                        h.Username("guest");
                        h.Password("guest");
                    });
                    
                    cfg.ConfigureEndpoints(context);
                    // cfg.UseMessageRetry(x => x.SetRetryPolicy(new RetryPolicyFactory()));
                });

                x.AddSagaStateMachine<CourierStateMachine,CourierState>()
                    .EntityFrameworkRepository(r =>
                    {
                        r.ConcurrencyMode = ConcurrencyMode.Optimistic;
                        
                        r.AddDbContext<DbContext,CourierServiceDbContext>((provider,builder) =>
                        {
                            builder.UseNpgsql(host.Configuration.GetConnectionString("OrdersConnection"),m =>
                            {
                                m.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name);
                                m.MigrationsHistoryTable($"__{nameof(CourierServiceDbContext)}");
                            });
                        });
                    });
            });

            services.AddMasstransitHostedService();
        });

解决方法

通过调试各种错误,我发现了一些必须做的事情:

  1. 向两个 DbContext 添加一个构造函数,它接受 DbContextOptions 而不是只有 DbContextOptions
  2. 使用上下文切换执行迁移创建,如“dotnet ef migrations add InitialCreate -c
  3. 使用上下文切换执行数据库同步命令,如“botnet ef database update -c

此外,您依赖 DbContext 的类应该注册为作用域,否则上述步骤将不起作用。

这将允许您在同一服务中注册多个 DbContext。