@@ -931,7 +931,7 @@ Expression ConvertExpressionToSystemConvertExpression()
931931 result = Expression . Call ( result , numberFormatMethod , [ Expression . Constant ( CultureInfo . InvariantCulture , typeof ( IFormatProvider ) ) ] ) ;
932932 }
933933#if NET
934- else if ( toType = = typeof ( Half ) )
934+ else if ( toType = = typeof ( Half ) && ( underlyingFromType . IsBinaryIntFloatOrDecimal ( ) || underlyingFromType == StaticType . Object ) )
935935 {
936936 // System.Converter doesn't support half, nor does 99% of DotNet. Just fall through to float/single support and convert from there
937937
@@ -965,17 +965,16 @@ Expression ConvertExpressionToSystemConvertExpression()
965965 result = Expression . Condition (
966966 Expression . TypeIs ( expression , underlyingToType ) ,
967967 // This case happens in PostgreSql bulktests
968- Expression . Convert ( expression , underlyingToType ) ,
969- // And this case is currently not triggered in tests. Ultimate fallback but **SLOW** as it does runtime reflection. Not compiletime
970- Expression . Convert (
971- Expression . Call ( systemChangeType ,
972- [
973- ConvertExpressionToTypeExpression ( result , StaticType . Object ) ,
974- Expression . Constant ( fromType , typeof ( Type ) ) ,
975- Expression . Constant ( underlyingToType , typeof ( Type ) ) ,
976- ] ) ,
977- underlyingToType )
978- ) ;
968+ Expression . Convert ( expression , typeof ( object ) ) ,
969+ // And this currently doesn't happen in tests, but hard failing because IConverable doesn't support types causes quite some issues
970+ Expression . Call ( systemChangeType ,
971+ [
972+ ConvertExpressionToTypeExpression ( result , StaticType . Object ) ,
973+ Expression . Constant ( fromType , typeof ( Type ) ) ,
974+ Expression . Constant ( underlyingToType , typeof ( Type ) ) ,
975+ ] )
976+ ) ;
977+
979978 }
980979
981980 // Do we need manual NULL handling?
@@ -1011,13 +1010,15 @@ Expression ConvertExpressionToSystemConvertExpression()
10111010
10121011 try
10131012 {
1014- if ( actualType is { } && ProviderSpecificTransforms . TryGetValue ( ( actualType , conversionType ) , out var metaTransform )
1015- && Expression . Parameter ( actualType ) is { } param
1016- && metaTransform ( param ) is { } transform )
1013+ if ( actualType is { } && Compiler . TryConvertViaProvider ( value , conversionType , actualType , out var newValue ) )
10171014 {
1018- return Expression . Lambda ( transform , param ) . Compile ( true ) . DynamicInvoke ( value ) ;
1015+ return newValue ;
10191016 }
1020- return Convert . ChangeType ( value , conversionType , CultureInfo . InvariantCulture ) ;
1017+
1018+ if ( value is IConvertible ) // Convert.ChangeType only supports system types that support IConvertable
1019+ return Convert . ChangeType ( value , conversionType , CultureInfo . InvariantCulture ) ;
1020+ else
1021+ return value ; // We can't convert it... fall through to the db provider, etc.
10211022 }
10221023 catch ( Exception ex )
10231024 {
@@ -1028,6 +1029,22 @@ static InvalidOperationException MakeException(Type? valueType, Type conversionT
10281029 => new InvalidOperationException ( $ "No declared converter found to convert value of type '{ valueType ? . FullName ?? "null" } ' (declared as'{ fromType . FullName } ') to type '{ conversionType . FullName } ', even via final reflection fallback.", innerException ) ;
10291030 }
10301031
1032+ internal static bool TryConvertViaProvider ( object value , Type toType , Type valueType , out object ? newValue )
1033+ {
1034+ // Perhaps the DB provider can do something smart here...
1035+ if ( ProviderSpecificTransforms . TryGetValue ( ( valueType , toType ) , out var metaTransform )
1036+ && Expression . Parameter ( valueType ) is { } param
1037+ && metaTransform ( param ) is { } transform )
1038+ {
1039+ newValue = Expression . Lambda ( transform , param ) . Compile ( true ) . DynamicInvoke ( value ) ;
1040+ return true ;
1041+ }
1042+ else
1043+ {
1044+ newValue = null ;
1045+ return false ;
1046+ }
1047+ }
10311048
10321049 private static Expression ConvertExpressionToPropertyHandlerGetExpression ( Expression expression ,
10331050 Expression readerExpression ,
0 commit comments