Skip to content

InExpression.Print() makes wrong assumption about Values property #17860

@lauxjpn

Description

@lauxjpn

We came across this issue, which we resolved by changing our code to the new assumption, but it should be checked, if this breaking change was intended.

https://github.com/aspnet/EntityFrameworkCore/blob/130fe39bed1c9351ba73a829aa14a6112108a6b2/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs#L55-L82

It is assumed here, that constantValues is an IEnumerable<SomeClrType>:

https://github.com/aspnet/EntityFrameworkCore/blob/130fe39bed1c9351ba73a829aa14a6112108a6b2/src/EFCore.Relational/Query/SqlExpressions/InExpression.cs#L61-L62

Additionally, it should be assumed (and checked), that constantValues is of type IEnumerable<SqlConstantExpression<SomeClrType>> and its items should be visited/printed.

The current (probably false) assumption can lead to exceptions being thrown further down the stack, when the InExpression is getting printed.

In case it is expected to call SqlExpressionFactory.In() only with an IEnumerable<SomeClrType> instead of IEnumerable<SqlConstantExpression<SomeClrType>> in 3.0 (which does work), this would be a breaking change from 2.2.6, where the latter works fine.


In our concrete case, we are creating an InExpression over StringComparison enum values by feeding it an SqlConstantExpression<IEnumerable<SqlConstantExpression<StringComparison>>>
Later, InExpression.Print() calls GenerateSqlLiteral(value: SqlConstantExpression(StringComparison:Ordinal)), which then calls the EnumToNumberConverter.
While the converter sanitizes the value, the following exception is thrown:

System.InvalidCastException: 'Object must implement IConvertible.'

This is due to the fact, that Sanitize<T>(object value) expects the concrete value, and not a value wrapped by a SqlExpression.

To fix this issue in our code base, we changed our call of SqlExpressionFactory.In() to use a SqlConstantExpression<IEnumerable<StringComparison>>.

Further technical details

EF Core version: 3.0+

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions