npgsql / efcore.pg

Entity Framework Core provider for PostgreSQL
PostgreSQL License
1.52k stars 223 forks source link

Npgsql.NpgsqlOperationInProgressException (0x80004005): A command is already in progress #2770

Open artworkad opened 1 year ago

artworkad commented 1 year ago

The line public string AuthorName => Author.Name; throws a Npgsql.NpgsqlOperationInProgressException (0x80004005): A command is already in progress exception.

public partial class Book
{
    //...

    public virtual Author Author { get; set; }

    public static void OnModelCreating(ModelBuilder modelBuilder)
    {
        OnModelCreating<Book>(modelBuilder);

        modelBuilder.Entity<Author>()
            .HasOne(p => p.Auhtor)
            .WithMany()
            .HasForeignKey("AuthorId");
    }
}

public partial class Book
{
    [NotMapped]
    public string AuthorName => Author.Name;
}

var authors = await _dbContext.Books
    .Select(x => x.Author)
    .ProjectTo<Author>(_mapper.ConfigurationProvider)
    .ToListAsync(cancellationToken);

Is this related to https://github.com/npgsql/npgsql/issues/462? I guess Author.Name is lazy loading the name in sub-query which is not supported. Any idea how to refactor that?

roji commented 1 year ago

I don't know what ProjectTo does exactly under the hood... The problem is coming from there.

artworkad commented 1 year ago

I don't know what ProjectTo does exactly under the hood... The problem is coming from there.

Thanks for the hint. I am going to investigate that. I am using automapper https://docs.automapper.org/en/stable/Projection.html That's where ProjectTo is coming from.

artworkad commented 1 year ago

@roji I created a minimal example to reproduce this https://github.com/artworkad/npgsql-issue

It is not related to ProjectTo and Automapper. Must be something else. You can post to http://localhost:5131/books

{
  "Title":"Test",
  "Author":{
      "Name": "Bob"
  }
}

and get http://localhost:5131/authors throws:

Npgsql.NpgsqlOperationInProgressException (0x80004005): A command is already in progress: SELECT b."Id", b."AuthorId", b."Title"
FROM "Books" AS b
   at Npgsql.Internal.NpgsqlConnector.<StartUserAction>g__DoStartUserAction|279_0(ConnectorState newState, NpgsqlCommand command, <>c__DisplayClass279_0&)
   at Npgsql.Internal.NpgsqlConnector.StartUserAction(ConnectorState newState, NpgsqlCommand command, CancellationToken cancellationToken, Boolean attemptPgCancellation)
   at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlCommand.ExecuteReader(CommandBehavior behavior)
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__21_0(DbContext _, Enumerator enumerator)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
Thijmen commented 1 month ago

I wonder what happened, in dotnet 8 I cannot reproduce the above repository @artworkad.