Reputation: 163
I have ~70 databases which are all exactly the same structure. What I am attempting to do is to create a quick Blazor (WASM/hosted) site on .net 6 which can access all of these sites using EF. Blazor is probably unimportant because all of the magic is happening in the 'hosted' portion which is really just a .Net API project.
So far, I have created a CommonDBContext which inherits DBContext and then individual DBContexts for each database which inherit CommonDBContext.
CommonDbContext.cs
public partial class CommonDbContext : DbContext
{
public CommonDbContext(DbContextOptions<CommonDbContext> options) : base(options)
{
}
protected CommonDbContext(DbContextOptions options) : base(options)
{
}
+2600 lines of EF scaffolding code
DB1-Context.cs
public partial class DB1Context : CommonDbContext
{
public DB1Context(DbContextOptions<DB1Context> options)
: base(options)
{
}
}
These various context are then injected in Program.cs
builder.Services.AddDbContext<DB1Context>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DB1"));
});
builder.Services.AddDbContext<DB2Context>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("DB2"));
});
I am not convinced this is a wonderful solution for 70 databases but it is a start. This approach seems to work perfectly - I can create a controller and whichever DB context I use, it seems to pull from the proper database.
Here's the problem
How can I select which DBContext I want to use in the controller? Building ~70 duplicate controllers seems very wrong but I haven't figured out how to pass in the DBContext from my request to the controller.
DopplegangerController.cs
[Route("api/[controller]")]
[ApiController]
public class DopplegangerController: ControllerBase
{
private DB1Context_context; // <-- RIGHT HERE
public DopplegangerController(DB1Contextcontext)
{
_context = context;
}
// GET: api/<DopplegangerController>
[HttpGet]
public List<Stuffs> Get()
{
return _context.Stuffs.ToList();
}
Upvotes: 2
Views: 170
Reputation: 733
In you Program.cs
when configuring your services, you can give a function that will fetch the connection string depending on your settings. This function will be call each time the DbContext needs to be injected.
builder.Services.AddDbContext<CommonDbContext>(getSQLOptions, ServiceLifetime.Transient);
void getSQLOptions(IServiceProvider serviceProvider, DbContextOptionsBuilder dbContextBuilder)
{
YourSettings? settings = serviceProvider.GetService<YourSettings>();
IHttpContextAccessor? httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
/* Get your connectionString from your settings and HttpContext (Can be headers, query param or whatever) */
dbContextBuilder.UseSqlServer(connectionString);
}
You can then just inject your unique CommonDbContext in your Controller and use it. You don't need the child DbContext anymore
Upvotes: 2