Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom ValueConverter generates correct SQL in expression eval but incorrect TSQL #33180

Open
jpenniman opened this issue Feb 27, 2024 · 1 comment

Comments

@jpenniman
Copy link

I have a scenario where I have a non-nullable column in my table but a my POCO model is nullable. (I know, not ideal. It's a brownfield and I'm trying to avoid a projection). I created a converter as follows:

class NullDecimalConverter : ValueConverter<decimal?, double>
{
    public NullDecimalConverter() : base(
        model => model == null ? 0 : (double)model,
        dbValue => dbValue == 0 ? null : (decimal)dbValue,
        convertsNulls: true
    )
    { }
}

Then mapped as follows:

model.Property(p => p.Quantity).HasColumnName("quantity").HasConversion(new NullDecimalConverter());

When use the following Linq query...

var po = db.ProposedOrders.Where(p => p.Quantity == null).ToList();

It generates the correct SQL at the start of the process, but the incorrect SQL to execute:

The select statement compiled here is correct...

dbug: 2/27/2024 15:35:42.293 CoreEventId.QueryExecutionPlanned[10107] (Microsoft.EntityFrameworkCore.Query) 
      Generated query execution expression: 
      'queryContext => new SingleQueryingEnumerable<ProposedOrder>(
          (RelationalQueryContext)queryContext, 
          RelationalCommandCache.QueryExpression(
              Projection Mapping:
                  EmptyProjectionMember -> Dictionary<IProperty, int> { [Property: ProposedOrder.Id (Id) Required PK AfterSave:Throw, 0], [Property: ProposedOrder.ComplianceStatus (SeverityLevel?), 1], [Property: ProposedOrder.Quantity (decimal?), 2] }
              SELECT p.order_id, p.compliance_check, p.quantity
              FROM proposed_orders AS p
              WHERE p.quantity == 0.0E0),
          null,
          Func<QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, ProposedOrder>,
          NullEnumsInEF.ReadDbContext,
          False,
          False,
          True
      )'

But then this is what it finally executed...

info: 2/27/2024 15:35:42.582 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
      Executed DbCommand (31ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT [p].[order_id], [p].[compliance_check], [p].[quantity]
      FROM [proposed_orders] AS [p]
      WHERE [p].[quantity] IS NULL

Ultimately, we'll probably end up solving it at the database level so no converters are necessary, but it struck me as odd that EF got it right on the first pass but didn't actually use that SQL.

Include provider and version information

EF Core version: 8.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 8.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.9)

@ajcvickers
Copy link
Member

Note for team triage: related to #26209 and #26210.

@ajcvickers ajcvickers self-assigned this Mar 10, 2024
@ajcvickers ajcvickers added this to the Backlog milestone Mar 12, 2024
@ajcvickers ajcvickers removed their assignment Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants