NpgsqlDatabaseCreator.Exist doesn't like DbConnectionInterceptor to open the connection

Aberta
#3,455 2 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
25/100
Tipo de issue
Bug
Clareza
Precisa de esclarecimento
Status de atividade
Estagnada
Stack de tecnologia
csharp, postgresql
Domínio
backend, databases

Direção de pesquisa

Start by reading the linked EF Core RelationalConnection.cs lines 758–767 and the referenced pull request #3349, then run the issue’s interceptor repro. The issue describes repeated ExistsAsync calls leaving the connection open and failing on the second call; done would mean the interceptor lifecycle behaves as expected and repeated calls no longer fail.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

We somehow had a DbConnectionInterceptor that opens a connection on ConnectionOpening. I thought it could be done

In EF Core, ConnectionOpened is invoked regardless of IsSuppressed value, so the interceptor should've opened the connection when IsSuppressed is true.
https://github.com/dotnet/efcore/blob/6cacf97e1093965928d27e99a7b3f90d25c0b01b/src/EFCore.Relational/Storage/RelationalConnection.cs#L758-L767

But after this change (https://github.com/npgsql/efcore.pg/pull/3349), we had errors (reproduced below) and connection leaks (couldn't reproduce in the test).

Here's the repro:

public sealed class TestContext : DbContext
{
    public TestContext(DbContextOptions<TestContext> options)
        : base(options)
    {
    }
}

public sealed class ConnectionOpeningInterceptor : DbConnectionInterceptor
{
    public override async ValueTask<InterceptionResult> ConnectionOpeningAsync(
        DbConnection connection, ConnectionEventData eventData, InterceptionResult result,
        CancellationToken cancellationToken = default)
    {
        await connection.OpenAsync(cancellationToken);
        return InterceptionResult.Suppress();
    }
}

var services = new ServiceCollection();
services.AddDbContext<TestContext>(options =>
{
    options.UseNpgsql("connection string");
    options.AddInterceptors(new ConnectionOpeningInterceptor());
});

await using var serviceProvider = services.BuildServiceProvider();
var context = serviceProvider.GetRequiredService<TestContext>();
var relationalDatabaseCreator = context.GetService<IRelationalDatabaseCreator>();

await relationalDatabaseCreator.ExistsAsync(); // okay, but doesn't close connection
await relationalDatabaseCreator.ExistsAsync(); // throws exception on the second invocation

I think the change slightly broke the semantics of the interceptor.
Before the change, The invocation of ConnectionOpening was always followed by the matching invocations of ConnectionOpened and ConnectionClosing or ConnectionDisposing if there were no errors.
But after the change, there is always one more invocation of ConnectionOpening

We removed the interceptor, so it doesn't necessarily need to be fixed for me, but I leave this issue as a future note.

Linguagem predominante
C#
Estrelas
1.8k
Forks
268
Merge médio
2h 35min
PRs com merge (30d)
136

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de npgsql/efcore.pg

Todas as issues de npgsql/efcore.pg

Issues semelhantes

Mais issues de C#

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.