efcore.pg icon indicating copy to clipboard operation
efcore.pg copied to clipboard

Changing the connection string from an interceptor doesn't work from migrations

Open roji opened this issue 2 years ago • 4 comments

See https://github.com/dotnet/efcore/issues/31055

roji avatar Sep 21 '23 12:09 roji

Just another simple console repro:

using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;

await using TestContext context = new();

await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

public class TestContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql();
        optionsBuilder.AddInterceptors(new ConnectionStringInitializationInterceptor(string.Empty));
        base.OnConfiguring(optionsBuilder);
    }
}

public class ConnectionStringInitializationInterceptor : DbConnectionInterceptor
{
    private readonly string _connectionString;

    internal ConnectionStringInitializationInterceptor(string connectionString)
    {
        _connectionString = connectionString;
    }

    public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)
    {
        if (string.IsNullOrEmpty(connection.ConnectionString))
        {
            connection.ConnectionString = _connectionString;
        }

        return result;
    }

    public async override ValueTask<InterceptionResult> ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrEmpty(connection.ConnectionString))
        {
            connection.ConnectionString = _connectionString;
        }

        return result;
    }
}

I'm not sure how far you've looked into this already, but to me it looks like there's some conflict of interest at this point.

When calling Exists inside of NpgsqlDatabaseCreator, the connection is enforced to be non-pooled. This overwrites the empty string and lets the NpgsqlConnection throw when being cloned due to missing values.

So on one hand the ConnectionString has to be correctly configured, but on the other it should be empty to be passed to the interceptors.

WhatzGames avatar Mar 23 '24 00:03 WhatzGames

@WhatzGames yeah, no, I haven't yet had any time to look at this - and it very well may be that the non-pooled change in EFCore.PG is the source of the issue. If that's really the problem, then it probably makes sense to specifically detect the empty string case and not rewrite?

roji avatar Mar 23 '24 08:03 roji

@roji yeah, that's what I thought too.

But in that case either there has to be a way to apply the same changes after the interceptor has assigned a new ConnectionString, but before the connection is opened, or the developer is made responsible for making sure that the connection is not pooled.

Unless of course the non-pooled config is not absolutely necessary for the connection. In that case I'll happily just skip.

WhatzGames avatar Mar 23 '24 10:03 WhatzGames

I'm experiencing this bug when running migrations in Aspire.

giammin avatar Oct 17 '24 10:10 giammin