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

Đang mở
#3,455 2 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
25/100
Loại issue
Lỗi
Độ rõ ràng
Cần làm rõ
Mức độ hoạt động
Đình trệ
Công nghệ
csharp, postgresql
Lĩnh vực
backend, databases

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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.

Ngôn ngữ chính
C#
Star
1.8k
Fork
268
Merge trung bình
2 giờ 35 phút
Pull request đã merge (30 ngày)
136

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của npgsql/efcore.pg

Tất cả issue của npgsql/efcore.pg

Issue tương tự

Thêm issue về C#

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.