levis84
levis84

Reputation: 1054

aspnet core change database connection string via middleware

My web api follows this structure

/countrycode/mycontroller e.g. /gbr/mycontroller I am using middleware to get the country code so I can switch connection string:

public class ConnectionMiddleware
{

public ConnectionMiddleware(RequestDelegate next)
{
    this.next = next;
}

private readonly RequestDelegate next;

public async Task InvokeAsync(HttpContext httpContext)
{            
    var values = httpContext.GetRouteData().Values;            
    await next(httpContext);
}

}

So now I have my country code I want to set the connection string property in my db service.

My db service is already registered in Startup.cs:

services.AddTransient<INpgSqlDataAccess, NpgSqlDataAccess>();

Can the connection string be set via my middleware now and be seen globally (after already being registered) or should I register the service in my middleware?

Upvotes: 3

Views: 1631

Answers (2)

mjolka
mjolka

Reputation: 831

If your DbContext is called AppDbContext, you can modify the connection string in middleware like this:

public async Task Invoke(
    HttpContext httpContext,
    IConfiguration configuration,
    AppDbContext context)
{
    context.Database.SetConnectionString(configuration.GetConnectionString("Other"));

    await _next(httpContext);
}

In Startup.ConfigureServices:

services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(Configuration.GetConnectionString("Default")));

Upvotes: 0

Arsalan Valoojerdi
Arsalan Valoojerdi

Reputation: 1026

First you should create a class for manage connection string.

public interface IDatabaseConnectionManager
{
    void SetConnectionString(string connectionString);
    string GetConnectionString();
}

public class DatabaseConnectionManager
{
    private string _connectionString;

    public DatabaseConnectionManager()
    {
        // _connectionString = DefaultConnectionString;
    }

    public void SetConnectionString(string connectionString)
    {
        this._connectionString = connectionString;      
    }

    public void GetConnectionString() {
        return _connectionString; 
    }
}

And then if you want to use middleware you can try this:

public class ConnectionMiddleware { private readonly RequestDelegate _next;

public async Task InvokeAsync(HttpContext httpContext,IDatabaaseConnectionManager connectionManager)
{
    var connectionString = "some-connection-string"; // Create Your Connection String Here

    connectionManager.SetConnectionString(connectionString);

    await _next.InvokeAsync(httpContext);
}

And in your Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IDatabaseConnectionManager,DatabaseConnectionManager>();
    services.AddScoped<INgpSqlDataAccess>(options=>
    {
        var connectionManager = options.GetService<IDatabaseConnectionManager>();
        var connectionString = connectionManager.GetConnectionString();

        // Create Your SqlDataAccess With ConnectionString
        return new NgpSqlDataAccess(connectionString);
    });
}

Every time you resolve INgpSqlDataAccess you get a new instance with your desired connectionstring. Be carefull that you must register your dependencies with per http request life time (Scoped).

Upvotes: 3

Related Questions