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+
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
constantValuesis anIEnumerable<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
constantValuesis of typeIEnumerable<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
InExpressionis getting printed.In case it is expected to call
SqlExpressionFactory.In()only with anIEnumerable<SomeClrType>instead ofIEnumerable<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
InExpressionoverStringComparisonenum values by feeding it anSqlConstantExpression<IEnumerable<SqlConstantExpression<StringComparison>>>Later,
InExpression.Print()callsGenerateSqlLiteral(value: SqlConstantExpression(StringComparison:Ordinal)), which then calls theEnumToNumberConverter.While the converter sanitizes the value, the following exception is thrown:
This is due to the fact, that
Sanitize<T>(object value)expects the concrete value, and not a value wrapped by aSqlExpression.To fix this issue in our code base, we changed our call of
SqlExpressionFactory.In()to use aSqlConstantExpression<IEnumerable<StringComparison>>.Further technical details
EF Core version: 3.0+