Skip to content

Conversation

@0xced
Copy link
Contributor

@0xced 0xced commented Dec 16, 2025

Pull request #108 made sure that EF Core async extensions (such as AnyAsync are properly translated to the System.Linq.Queryable.Any extension method).

Unfortunately, this introduced a regression. When async and sync methods are in the same extension class (such as ExecuteDeleteAsync and ExecuteDelete) the generated sync method would be wrong. I.e., generated in System.Linq.Queryable instead of Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.

This pull request tries to address this issue. Unfortunately, I'm again facing discrepancies between the GenerationSandbox.Tests and Generator.Tests projects. This is why this pull request is opened a draft.

When used in the GenerationSandbox.Tests project, the generated code is correct.

// <auto-generated/>
#nullable enable
namespace GenerationSandbox.Tests
{
    public partial class EntityFrameworkQueryableExtensions
    {
        /// <summary>
        /// Test method.
        /// </summary>
        /// <param name="dbContext">The db context.</param>
        /// <returns>The result.</returns>
        public int QueryableExtension(global::Microsoft.EntityFrameworkCore.DbContext dbContext)
        {
            var dbSet = dbContext.Set<object>();
            if (global::System.Linq.Queryable.Any(dbSet))
            {
                return global::Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteDelete(dbSet);
            }

            return 0;
        }
    }
}

When generated in the Generator.Tests project, the generated code is incorrect. Note how the
Any and ExecuteDelete methods are not generated with their fully qualified names.

//HintName: Zomp.SyncMethodGenerator.IntegrationTests.EntityFrameworkQueryableExtensions.QueryableExtensionAsync.g.cs
// <auto-generated/>
#nullable enable
namespace Zomp.SyncMethodGenerator.IntegrationTests
{
    public partial class EntityFrameworkQueryableExtensions
    {
        public int QueryableExtension(global::Microsoft.EntityFrameworkCore.DbContext dbContext)
        {
            var dbSet = dbContext.Set<object>();
            if (dbSet.Any())
            {
                return dbSet.ExecuteDelete();
            }
            
            return 0;
        }
    }
}

I don't understand why the generated code is different. I have identified that var symbol = GetSymbol(node) returns null for InvocationExpressionSyntax InvocationExpression dbSet.AnyAsync(cancellationToken) in Generator.Tests and not null in GenerationSandbox.Tests but I don't understand why.

@0xced 0xced marked this pull request as draft December 16, 2025 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant