dotnet / dotnet/efcore

Custom ValueConverter generates correct SQL in expression eval but incorrect TSQL

Open
#33,180 1 comment 0 reactions 0 assignees View on GitHub
area-change-tracking customer-reported needs-design
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

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:

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

Then mapped as follows:

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

When use the following Linq query...

``` cs
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(
(RelationalQueryContext)queryContext,
RelationalCommandCache.QueryExpression(
Projection Mapping:
EmptyProjectionMember -> Dictionary { [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,
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)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.