Dynamically change connection string in Asp.Net Core
We have a case similar to you. What we've done is use the implementationfactory overload of the IServiceCollection in the ConfigureServices method of the Startup class, like so:
//First register a custom made db context provider
services.AddTransient<ApplicationDbContextFactory>();
//Then use implementation factory to get the one you need
services.AddTransient(provider => provider.GetService<ApplicationDbContextFactory>().CreateApplicationDbContext());
It is very difficult for me right now to implement CreateApplicationDbContext for you, because it totally depends on what you want exactly. But once you've figured that part out how you want to do it exactly, the basics of the method should look like this anyway:
public ApplicationDbContext CreateApplicationDbContext(){
//TODO Something clever to create correct ApplicationDbContext with ConnectionString you need.
}
Once this is implemented you can inject the correct ApplicationDbContext in your controller like you did in the constructor:
public MyController(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
Or an action method in the controller:
public IActionResult([FromServices] ApplicationDbContext dbContext){
}
However you implement the details, the trick is that the implementation factory will build your ApplicationDbContext everytime you inject it.
Tell me if you need more help implementing this solution.
Update #1
Yuriy N. asked what's the difference between AddTransient and AddDbContext, which is a valid question... And it isn't. Let me explain.
This is not relevant for the original question.
BUT... Having said that, implementing your own 'implementation factory' (which is the most important thing to note about my answer) can in this case with entity framework be a bit more tricky than what we needed.
However, with questions like these we can nowadays luckily look at the sourcecode in GitHub, so I looked up what AddDbContext does exactly. And well... That is not really difficult. These 'add' (and 'use') extension methods are nothing more than convenience methods, remember that. So you need to add all the services that AddDbContext does, plus the options. Maybe you can even reuse AddDbContext extension method, just add your own overload with an implementation factory.
So, to come back to your question. AddDbContext does some EF specific stuff. As you can see they are going to allow you to pass a lifetime in a later release (transient, singleton). AddTransient is Asp.Net Core which allows you to add any service you need. And you need an implementation factory.
Does this make it more clear?
How to dynamically change connection string ASP.NET
You can't change the settings based on the http request in ConfigureServices
. Instead you should implement an abstract factory. A full response with example you may find here:
How to configure services based on request in ASP.NET Core
asp.net core how to change connection string at run time from entity framework (after login)
IMO,you could not change the services.AddDbContext<T>
at runtime.A workaround is that you add a DBContextFactory
to create new dbcontext object when you login successfully.
Refer to following steps:
1.Create a DBContextFactory.cs
public static class DbContextFactory
{
public static Dictionary<string, string> ConnectionStrings { get; set; }
public static void SetConnectionString(Dictionary<string, string> connStrs)
{
ConnectionStrings = connStrs;
}
public static ApplicationDbContext Create(string connid)
{
if (!string.IsNullOrEmpty(connid))
{
var connStr = ConnectionStrings[connid];
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(connStr);
return new ApplicationDbContext(optionsBuilder.Options);
}
else
{
throw new ArgumentNullException("ConnectionId");
}
}
}
2.Intialize DbContextFactory in startup Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Dictionary<string, string> connStrs = new Dictionary<string, string>();
connStrs.Add("DB1", "Your connection string 1");
connStrs.Add("DB2", "Your connection string 2");
DbContextFactory.SetConnectionString(connStrs);
//other middlewares
}
3.Usage
if(status)
{
var dbContext = DbContextFactory.Create("DB2");//get the dbcontext with connection string 2
}
Make dynamically HangFire connection string .NetCore
Do not hard code the connection string.
Store it in the appsettings.json file
For example
{
"ConnectionStrings": {
"Hangfire": "server=127.0.0.1;uid=root;database=0046696-k; Allow User Variables=True"
}
/* other settings */
}
and load it at startup.
//...Assume IConfiguration Configuration is loaded
//...
string connectionString = Configuration.GetConnectionString("Hangfire"); //<-- NOTE
services.AddHangfire(configuration => configuration.UseStorage(
new MySqlStorage(connectionString, //<-- NOTE
new MySqlStorageOptions() {
TransactionIsolationLevel = (System.Transactions.IsolationLevel?)IsolationLevel.ReadCommitted,
QueuePollInterval = TimeSpan.FromSeconds(15),
JobExpirationCheckInterval = TimeSpan.FromHours(1),
CountersAggregateInterval = TimeSpan.FromMinutes(5),
PrepareSchemaIfNecessary = true,
DashboardJobListLimit = 50000,
TransactionTimeout = TimeSpan.FromMinutes(1),
TablesPrefix = "Hangfire"
})));
services.AddHangfireServer();
//...
That way you only need to edit the settings file as desired.
If the options need to change dynamically as well then add a section in the settings to hold the desired options and load them in Startup.
Related Topics
Tolist()-- Does It Create a New List
Multiple Httppost Method in Web API Controller
Using Global Keyboard Hook (Wh_Keyboard_Ll) in Wpf/C#
Add Data Annotations to a Class Generated by Entity Framework
Random String Generator Returning Same String
Calculating Distance Between Two Latitude and Longitude Geocoordinates
How to Check the Number of Bytes Consumed by a Structure
If Statements Matching Multiple Values
How to Catch Exception in Task
Headless Browser for C# (.Net)
How to Get a Property Value Based on the Name
How to Animate a Line on a Canvas in C#
How to Get the Title of the Current Active Window Using C#