There is an issue with the null handling in column values when mapping to objects, as per my simple example below. running SL as simple as:
SELECT 1 AS ResultCode, NULL as Message
and trying to map that to a result object that has int and string fields. The issue seems to be with the NULL. If I change the SQL to SELECT 1 AS ResultCode, '' as Message then the mapping will work.
Exception Message:
Failed to get result: System.InvalidOperationException: Compiler.DataReader.IsDbNull.FalseExpression: Failed to convert the value expression into its destination .NET CLR Type 'System.String'. PropertyInfo: Message (System.String), DeclaringType: RepoDbTest.Result
---> System.InvalidOperationException: No coercion operator is defined between types 'System.Int32' and 'System.String'.
at System.Linq.Expressions.Expression.GetUserDefinedCoercionOrThrow(ExpressionType coercionType, Expression expression, Type convertToType)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type, MethodInfo method)
at System.Linq.Expressions.Expression.Convert(Expression expression, Type type)
at RepoDb.Reflection.Compiler.ConvertExpressionToTypeExpression(Expression expression, Type toType)
at RepoDb.Reflection.Compiler.GetClassPropertyParameterInfoIsDbNullFalseValueExpression(ParameterExpression readerParameterExpression, ClassPropertyParameterInfo classPropertyParameterInfo, DataReaderField readerField)
--- End of inner exception stack trace ---
at RepoDb.Reflection.Compiler.GetClassPropertyParameterInfoIsDbNullFalseValueExpression(ParameterExpression readerParameterExpression, ClassPropertyParameterInfo classPropertyParameterInfo, DataReaderField readerField)
at RepoDb.Reflection.Compiler.GetClassPropertyParameterInfoValueExpression(ParameterExpression readerParameterExpression, ClassPropertyParameterInfo classPropertyParameterInfo, DataReaderField readerField)
at RepoDb.Reflection.Compiler.GetMemberBindingsForDataEntity[TResult](ParameterExpression readerParameterExpression, IEnumerable`1 readerFields, IDbSetting dbSetting)
at RepoDb.Reflection.Compiler.CompileDataReaderToDataEntity[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.Compiler.CompileDataReaderToType[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.FunctionFactory.CompileDataReaderToType[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.FunctionCache.DataReaderToTypeCache`1.Get(DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.FunctionCache.GetDataReaderToTypeCompiledFunction[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)
at RepoDb.Reflection.DataReader.ToEnumerable[TResult](DbDataReader reader, IEnumerable`1 dbFields, IDbSetting dbSetting)+MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at RepoDb.Extensions.EnumerableExtension.AsList[T](IEnumerable`1 value)
at RepoDb.DbConnectionExtension.ExecuteQueryInternalForType[TResult](IDbConnection connection, String commandText, Object param, Nullable`1 commandType, String cacheKey, Nullable`1 cacheItemExpiration, Nullable`1 commandTimeout, IDbTransaction transaction, ICache cache, String tableName, Boolean skipCommandArrayParametersCheck)
at RepoDb.DbConnectionExtension.ExecuteQueryInternal[TResult](IDbConnection connection, String commandText, Object param, Nullable`1 commandType, String cacheKey, Nullable`1 cacheItemExpiration, Nullable`1 commandTimeout, IDbTransaction transaction, ICache cache, String tableName, Boolean skipCommandArrayParametersCheck)
at RepoDb.DbConnectionExtension.ExecuteQuery[TResult](IDbConnection connection, String commandText, Object param, Nullable`1 commandType, String cacheKey, Nullable`1 cacheItemExpiration, Nullable`1 commandTimeout, IDbTransaction transaction, ICache cache)
at RepoDbTest.Program.Main(String[] args)
Example Code:
using System;
using System.Data;
using System.Data.SqlClient;
using RepoDb;
namespace RepoDbTest
{
class Program
{
static void Main(string[] args)
{
SqlServerBootstrap.Initialize();
string conn = "Server=.;Trusted_Connection=True;MultipleActiveResultSets=true";
try
{
using (IDbConnection connection = new SqlConnection(conn).EnsureOpen())
{
var result = connection.ExecuteQuery<Result>("SELECT 1 AS ResultCode, NULL as Message");
Console.WriteLine("Successfully got result");
}
}
catch (Exception e)
{
Console.WriteLine("Failed to get result: " + e);
}
}
}
public class Result
{
public int ResultCode { get; set; }
public string Message { get; set; }
}
}
Library Version:
Example: RepoDb v1.12.7 and RepoDb.SqlServer v1.1.3
Ignore this - as described in Gitter by Mike the issue is not giving a type to that SQL expression like (CONVERT(VARCHAR(50),NULL) AS Message) and by default RepoDb assumes it is an int column
Bug Description
There is an issue with the null handling in column values when mapping to objects, as per my simple example below. running SL as simple as: SELECT 1 AS ResultCode, NULL as Message
and trying to map that to a result object that has int and string fields. The issue seems to be with the NULL. If I change the SQL to SELECT 1 AS ResultCode, '' as Message then the mapping will work.
Exception Message:
Example Code:
Library Version:
Example: RepoDb v1.12.7 and RepoDb.SqlServer v1.1.3