0

I'm trying to use two different databases in one api.

These are the contexts:

public class DatabaseOneDBContext : DbContext, IDatabaseOneDBContext
{
    public DatabaseOneDBContext(DbContextOptions<DatabaseOneDBContext> options)
        : base(options)
    {

    }

    public DbSet<Alena> Alena { get; set; }

    public async Task<int> SaveChangesAsyncOne()
    {
        return await base.SaveChangesAsync(); 
    }
}

public class DatabaseTwoDBContext : DbContext, IDatabaseTwoDBContext
{
    private readonly IDatabaseTwoDBContext _context;

    public DatabaseTwoDBContext(IDatabaseTwoDBContext context)
    {
        this._context = context;
    }

    public DbSet<Cortana> Cortana { get; set; }

    public async Task<int> SaveChangesAsyncTwo()
    {
        return await base.SaveChangesAsync(); 
    }
}

appsettings.json

"ConnectionStrings": {
    "ConnectionDB1": "Server=.\\SQLEXPRESS;Database=DatabaseOne;Trusted_Connection=True;MultipleActiveResultSets=true",
    "ConnectionDB2": "Server=.\\SQLEXPRESS;Database=DatabaseTwo;Trusted_Connection=True;MultipleActiveResultSets=true"
},

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Forecast.DatabaseOne;
using Forecast.DatabaseOne.Contracts;
using Forecast.ServiceOne.Contracts;
using Forecast.ServiceOne;
using Serilog;
using Forecast.DatabaseTwo;
using Forecast.DatabaseTwo.Contracts;
using Forecast.ServiceTwo.Contracts;
using Forecast.ServiceTwo;

namespace Forecast.Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(Configuration)
                .CreateLogger();
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DatabaseOneDBContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("ConnectionDB1"),
                    ef => ef.MigrationsAssembly("Forecast.DatabaseOne")));

            services.AddScoped<IDatabaseOneDBContext>(provider => provider.GetService<DatabaseOneDBContext>());

            services.AddDbContext<DatabaseTwoDBContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("ConnectionDB2"),
                    ef => ef.MigrationsAssembly("Forecast.DatabaseTwo")));

            services.AddScoped<IDatabaseTwoDBContext>(provider => provider.GetService<DatabaseTwoDBContext>());

            services.AddTransient<IAlenaService, AlenaService>();
            services.AddTransient<ICortanaService, CortanaService>();

            services.AddApiVersioning(apiVerConfig =>
            {
                apiVerConfig.AssumeDefaultVersionWhenUnspecified = true;
                apiVerConfig.DefaultApiVersion = new ApiVersion(new DateTime(2022, 1, 22));
            });

            services.AddHealthChecks()
                .AddDbContextCheck<DatabaseOneDBContext>();

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1a", new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Title = "ForecastService - Alena Web API",
                    Version = "v1a",
                    Description = "test service"
                });
            });

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            app.UseHealthChecks("/checkhealth");

            app.UseSwagger();
            app.UseSwaggerUI(options =>
                {
                    options.SwaggerEndpoint("/swagger/v1a/swagger.json", "Alena API v1a");
                });
        }
    }
}

When I use this

add-migration -context DatabaseOneDBContext 
update-database -context DatabaseOneDBContext 

it works and default project is DatabaseOne, but when I try to do the same thing for DatabaseTwoDBContext (I change the default project to DatabaseTwo), it just sleeps the process and I have to restart my PC so I can try again.

Help me solve this

1
  • You don't need to separately call AddScoped<IDatabaseOneDBContext> to inject your context. AddDbContext<> does that for you in the background. Not sure whether this is what is causing your error however, so not posting it as an answer. But it might be your migration getting confused with which instance to use. Commented Mar 17, 2022 at 14:42

1 Answer 1

1

it seems to me that you need to replace this line with the same one as in the first context

Try change this

  private readonly IDatabaseTwoDBContext _context;

  public DatabaseTwoDBContext(IDatabaseTwoDBContext context)
  {
      this._context = context;
  }

To this

public DatabaseOneDBContext(DbContextOptions<DatabaseTwoDBContext> options)
    : base(options)
{

}

Perhaps the second context is recursively trying to resolve the dependency IDatabaseTwoDBContext in constructor

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.