1
votes

I have a .Net Core 2.1 Web API talking to a MySQL database, using the Pomelo provider (version 2.1.0-rc1-final). Because this is a multi-tenant application, the API needs to change databases depending on which tenant is connecting. The front end web app tells the API which tenant is doing the request by including a TenantId header in the HTPP request.

When the API receives an HTTP request from the front end, I have a service in the API's pipeline that reads the TenantId from the request, and then this is used to determine which database the API must connect to.

To connect to various databases, I change the connection string of the DbContext. I do this in the OnConfiguring event:

protected override void OnConfiguring(DbContextOptionsBuilder options)
{
    string connectionString = CreateConnectionString();
    optionsBuilder.UseMySql(connectionString);
    base.OnConfiguring(optionsBuilder);
}

My problem is that this works the first time, but the second time this event fires, when it executes the optionsBuilder.UseMySql(connectionString); line, it throws this exception:

An item with the same key has already been added. Key: Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal.MySqlOptionsExtension

It's only letting me configure the DbContext once. I need to reconfigure it every time an API action endpoint gets called. Any ideas?

1
did you find the solution? It's happening exactly the same to me...John Mathison
To be honest, I'm not 100% sure what I did - but it's working now lol. But the process is as follows: I created middleware to identify the tenant making the request (i.e. consuming the API). This is done by reading a "tenantId" that the client app sends in the header of the request, and then saving that tenantId into a global variable (I used HttpContext). Because middleware executes before pretty much most other things, by the time the OnConfiguring event of the dbContext fires, I already know which tenant this is... (continued below)Fabricio Rodriguez
...So then, on the OnConfiguring event of the dbContext, I set the connectionString of the dbContext to whatever it should be (depending on the tenantId). I can't post the code in this comment because comments don't allow line breaks and they are too short, but If you want to, send me your email address and I'll email you the code.Fabricio Rodriguez
If this solved your issue, you should post it as an answer.HazardousGlitch
Thanks HazardousGlitch. I completely forgot to close this question. Will do so nowFabricio Rodriguez

1 Answers

0
votes

I'm not 100% sure what I did - but it's working now. The process is as follows: I created middleware to identify the tenant making the request (i.e. consuming the API). This is done by reading a "tenantId" that the client app sends in the header of the request, and then saving that tenantId into a global variable (I used HttpContext). Because middleware executes before pretty much most other things, by the time the OnConfiguring event of the dbContext fires, I already know which tenant this is So then, on the OnConfiguring event of the dbContext, I set the connectionString of the dbContext to whatever it should be (depending on the tenantId). I can't post the code in this comment because comments don't allow line breaks and they are too short, but If you want to, send me your email address and I'll email you the code.