Reputation: 642
I want to do some reporting in a ASP.NET Core web site that reads data from multiple databases using the same schema.
In Startup.cs
I need to have something like:
public void ConfigureServices(IServiceCollection services)
{
// Some other stuff here.
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("FirstConnectionString")));
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SecondConnectionString")));
}
But now the DbContext are of the same type and have no name, so how do I select the one I want to use in a controller?
public class HomeController : Controller
{
private readonly MyContext context;
public HomeController(MyContext context)
{
// Is that the one with FirstConnectionString or SecondConnectionString?
// How do I choose?
this.context = context;
}
}
EDIT:
I'm probably missing something but in MyContext
I have:
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
// Some more code here.
}
Then in MyContext1
I have:
public class MyContext1 : MyContext
{
// base in now MyContext and not DbContext !!!
// Error with: public MyContext1(DbContextOptions<MyContext1> options) : base(options)
public MyContext1(DbContextOptions<MyContext> options) : base(options)
{
}
}
If I add 2 derived types in startup and run it crashes and gives the following error message:
InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[MyContext]' while attempting to activate 'MyContext1'.
If I also add the base type in startup (so 3 types with 3 different connection strings) then all 3 types use the connection string of the base type.
Upvotes: 3
Views: 1679
Reputation: 2773
Why not just create two DbContexts? In theory, making 3 is probably cleaner .. keep the MyContext that you have set up, and then just create a Db1Context and Db2Context that inherit from it? means your registration ends up as
services.AddDbContext<Db1Context>(options => options.UseSqlServer(Configuration.GetConnectionString("FirstConnectionString")));
services.AddDbContext<Db2Context>(options => options.UseSqlServer(Configuration.GetConnectionString("SecondConnectionString")));
so then its easy to resolve, and due to inheritance you avoid some code duplication.. but I see no benefit from trying to keep 1 dbcontext that goes to multiple db in the same app
Edit: If you are still having some troubles with DI working, there was a fairly old thread on the Github that looks like someone having this type of issue which they resolved by doing
public class EFDbContext : DbContext
{
public EFDbContext(DbContextOptions<EFDbContext> options) : base(options) { }
protected MainDbContext(DbContextOptions options) : base(options) { }
}
public class DimensionsDbContext : EFDbContext
{
public DimensionsDbContext(DbContextOptions<DimensionsDbContext> options) : base(options) { }
}
something along those lines, having a second protected constructor in the class that inherits from dbcontext, to allow for the further inherited classes to use that. I mean, I wasnt able to re-create the issue on my end but that solution still also works for me, so may help in terms of getting it working for you
Upvotes: 5
Reputation: 642
I'm creating the multiple contexts in my reporting controllers in the end. It's not the DI way, but it works.
I have something like the following code in the controller constructor:
var firstOptionsBuilder = new DbContextOptionsBuilder<MyContext>();
firstOptionsBuilder.UseSqlServer("firstConnectionString");
var firstContext = new MyContext(firstOptionsBuilder.Options);
Upvotes: -1