0
votes

I have a console app that has two DbContexts. One is configured using MassTransit and the other is a reference to another project for which I already run migrations for. So, I want to run migrations on this service for the MassTransit configured DbContext and I get the following error message:

"More than one DbContext was found. Specify which one to use. Use the '-Context' parameter for PowerShell commands and the '--context' parameter for dotnet commands."

However, when I specify the context using "dotnet ef migrations add InitialCreate -c CourierServiceDbContext", I get the following error:

"Unable to create an object of type 'CourierServiceDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728"

To be clear, I only want to run migrations for the MassTransit configured DbContext, CourierServiceDbContext and not the referenced 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
Don't think this is related. I think the difference is that I have 2 projects, P1 and P2. P1 has a DbContext which I can successfully run ef migrations for. However, in P2 I have state machines for which I need to run migrations against but I also have consumers that reference the DbContext in P1, therefore, I need to register both DbContexts in the HostBuilder. - Albert
Commenting out the registration code that references the P1 DbContext allows me to run migrations using the dotnet ef migrations add InitialCreate -c MyMassTransitDbContext. - Albert

1 Answers

0
votes

I found a couple of things I had to do through debugging the various errors:

  1. Add a constructor to both DbContexts that takes DbContextOptions instead of just having DbContextOptions
  2. Perform the migration creation with the context switch as in "dotnet ef migrations add InitialCreate -c <your_dbcontext>"
  3. Perform the database sync command with the context switch as in "botnet ef database update -c <your_dbcontext>"

Also, your class that is depends on DbContext should be registered as scoped or else the above steps will not work.

This will allow you to have multiple DbContexts registered in the same service.