public void NullableParameterInOperatorConvert() { var(convertFromDecimalLambdaExpression1, convertFromDecimalLambdaExpression2, b1) = ConvertBuilder.GetConverter(null, typeof(decimal), typeof(CustomMoneyType)); var convertFromDecimalFunc1 = (Func <decimal, CustomMoneyType>)convertFromDecimalLambdaExpression1.Compile(); var convertFromDecimalFunc2 = (Func <decimal, CustomMoneyType>)convertFromDecimalLambdaExpression2.Compile(); Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, convertFromDecimalFunc1(1.11m)); Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, convertFromDecimalFunc2(1.11m)); var(convertFromNullableDecimalLambdaExpression1, convertFromNullableDecimalLambdaExpression2, b2) = ConvertBuilder.GetConverter(null, typeof(decimal?), typeof(CustomMoneyType)); var convertFromNullableDecimalFunc1 = (Func <decimal?, CustomMoneyType>)convertFromNullableDecimalLambdaExpression1.Compile(); var convertFromNullableDecimalFunc2 = (Func <decimal?, CustomMoneyType>)convertFromNullableDecimalLambdaExpression2.Compile(); Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, convertFromNullableDecimalFunc1(1.11m)); Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, convertFromNullableDecimalFunc2(1.11m)); Assert.AreEqual(new CustomMoneyType { Amount = null }, convertFromNullableDecimalFunc1(null)); Assert.AreEqual(new CustomMoneyType { Amount = null }, convertFromNullableDecimalFunc2(null)); }
public void ConvertNullableEnum() { var schema = new MappingSchema("2"); Assert.That(schema.GetDefaultValue(typeof(Enum1?)), Is.Null); var mapType = ConvertBuilder.GetDefaultMappingFromEnumType(schema, typeof(Enum1?)); Assert.That(mapType, Is.EqualTo(typeof(int?))); var convertedValue = Converter.ChangeType(null, mapType, schema); Assert.IsNull(convertedValue); }
public object EnumToValue(Enum value) { var toType = ConvertBuilder.GetDefaultMappingFromEnumType(this, value.GetType()); return(Converter.ChangeType(value, toType, this)); }
static Expression GetColumnReader( IDataContext dataContext, MappingSchema mappingSchema, IDataReader dataReader, Type type, int idx, Expression dataReaderExpr) { var toType = type.ToNullableUnderlying(); var ex = dataContext.GetReaderExpression(mappingSchema, dataReader, idx, dataReaderExpr, toType); if (ex.NodeType == ExpressionType.Lambda) { var l = (LambdaExpression)ex; switch (l.Parameters.Count) { case 1: ex = l.GetBody(dataReaderExpr); break; case 2: ex = l.GetBody(dataReaderExpr, Constant(idx)); break; } } if (toType.IsEnumEx()) { var mapType = ConvertBuilder.GetDefaultMappingFromEnumType(mappingSchema, toType); if (mapType != ex.Type) { // Use only defined convert var econv = mappingSchema.GetConvertExpression(ex.Type, type, false, false) ?? mappingSchema.GetConvertExpression(ex.Type, mapType, false); if (econv.Body.GetCount(e => e == econv.Parameters[0]) > 1) { var variable = Variable(ex.Type); var assign = Assign(variable, ex); ex = Block(new[] { variable }, new[] { assign, econv.GetBody(variable) }); } else { ex = econv.GetBody(ex); } } } var conv = mappingSchema.GetConvertExpression(ex.Type, type, false); // Replace multiple parameters with single variable or single parameter with the reader expression. // if (conv.Body.GetCount(e => e == conv.Parameters[0]) > 1) { var variable = Variable(ex.Type); var assign = Assign(variable, ex); ex = Block(new[] { variable }, new[] { assign, conv.GetBody(variable) }); } else { ex = conv.GetBody(ex); } // Add check null expression. // Note: Oracle may return wrong IsDBNullAllowed, so added additional check toType != type, that means nullable type // if (toType != type || (dataContext.IsDBNullAllowed(dataReader, idx) ?? true)) { ex = Condition( Call(dataReaderExpr, _isDBNullInfo, Constant(idx)), Constant(mappingSchema.GetDefaultValue(type), type), ex); } return(ex); }
private static DataParameter[] GetDataParameters(DataConnection dataConnection, object parameters) { if (parameters == null) { return(null); } var dataParameters = parameters as DataParameter[]; if (dataParameters != null) { return(dataParameters); } var parameter = parameters as DataParameter; if (parameter != null) { return new[] { parameter } } ; Func <object, DataParameter[]> func; var type = parameters.GetType(); var key = new ParamKey(type, dataConnection.ID); if (!_parameterReaders.TryGetValue(key, out func)) { var td = dataConnection.MappingSchema.GetEntityDescriptor(type); var p = Expression.Parameter(typeof(object), "p"); var obj = Expression.Parameter(parameters.GetType(), "obj"); var expr = Expression.Lambda <Func <object, DataParameter[]> >( Expression.Block( new[] { obj }, Expression.Assign(obj, Expression.Convert(p, type)), Expression.NewArrayInit( typeof(DataParameter), td.Columns.Select(m => { if (m.MemberType == typeof(DataParameter)) { var pobj = Expression.Parameter(typeof(DataParameter)); return(Expression.Block( new[] { pobj }, Expression.Assign(pobj, Expression.PropertyOrField(obj, m.MemberName)), Expression.MemberInit( Expression.New(typeof(DataParameter)), Expression.Bind( _dataParameterName, Expression.Coalesce( Expression.MakeMemberAccess(pobj, _dataParameterName), Expression.Constant(m.ColumnName))), Expression.Bind( _dataParameterDataType, Expression.MakeMemberAccess(pobj, _dataParameterDataType)), Expression.Bind( _dataParameterValue, Expression.Convert( Expression.MakeMemberAccess(pobj, _dataParameterValue), typeof(object)))))); } var memberType = m.MemberType.ToNullableUnderlying(); var valueGetter = Expression.PropertyOrField(obj, m.MemberName) as Expression; var mapper = dataConnection.MappingSchema.GetConvertExpression(memberType, typeof(DataParameter), createDefault: false); if (mapper != null) { return(Expression.Call( MemberHelper.MethodOf(() => PrepareDataParameter(null, null)), mapper.GetBody(valueGetter), Expression.Constant(m.ColumnName))); } if (memberType.IsEnum) { var mapType = ConvertBuilder.GetDefaultMappingFromEnumType(dataConnection.MappingSchema, memberType); var convExpr = dataConnection.MappingSchema.GetConvertExpression(m.MemberType, mapType); memberType = mapType; valueGetter = convExpr.GetBody(valueGetter); } return((Expression)Expression.MemberInit( Expression.New(typeof(DataParameter)), Expression.Bind( _dataParameterName, Expression.Constant(m.ColumnName)), Expression.Bind( _dataParameterDataType, Expression.Constant( dataConnection.MappingSchema.GetDataType(memberType).DataType)), Expression.Bind( _dataParameterValue, Expression.Convert(valueGetter, typeof(object))))); }))), p); _parameterReaders[key] = func = expr.Compile(); } return(func(parameters)); }
static Expression GetColumnReader( IDataContext dataContext, MappingSchema mappingSchema, IDataReader dataReader, Type type, IValueConverter?converter, int idx, Expression dataReaderExpr, bool forceNullCheck) { var toType = type.ToNullableUnderlying(); Expression ex; if (converter != null) { var expectedProvType = converter.FromProviderExpression.Parameters[0].Type; ex = dataContext.GetReaderExpression(dataReader, idx, dataReaderExpr, expectedProvType); } else { ex = dataContext.GetReaderExpression(dataReader, idx, dataReaderExpr, toType); } if (ex.NodeType == ExpressionType.Lambda) { var l = (LambdaExpression)ex; switch (l.Parameters.Count) { case 1: ex = l.GetBody(dataReaderExpr); break; case 2: ex = l.GetBody(dataReaderExpr, ExpressionInstances.Int32(idx)); break; } } if (converter != null) { // we have to prepare read expression to conversion // var expectedType = converter.FromProviderExpression.Parameters[0].Type; if (converter.HandlesNulls) { ex = Condition( Call(dataReaderExpr, Methods.ADONet.IsDBNull, ExpressionInstances.Int32Array(idx)), Constant(mappingSchema.GetDefaultValue(expectedType), expectedType), ex); } if (expectedType != ex.Type) { ex = ConvertExpressionToType(ex, expectedType, mappingSchema); } ex = InternalExtensions.ApplyLambdaToExpression(converter.FromProviderExpression, ex); if (toType != ex.Type && toType.IsAssignableFrom(ex.Type)) { ex = Convert(ex, toType); } } else if (toType.IsEnum) { var mapType = ConvertBuilder.GetDefaultMappingFromEnumType(mappingSchema, toType) !; if (mapType != ex.Type) { // Use only defined convert var econv = mappingSchema.GetConvertExpression(ex.Type, type, false, false) ?? mappingSchema.GetConvertExpression(ex.Type, mapType, false) !; ex = InternalExtensions.ApplyLambdaToExpression(econv, ex); } } if (ex.Type != type) { ex = ConvertExpressionToType(ex, type, mappingSchema) !; } // Try to search postprocessing converter TType -> TType // ex = ConvertExpressionToType(ex, ex.Type, mappingSchema) !; // Add check null expression. // If converter handles nulls, do not provide IsNull check // Note: some providers may return wrong IsDBNullAllowed, so we enforce null check in slow mode. E.g.: // Microsoft.Data.SQLite // Oracle (group by columns) // MySql.Data and some other providers enforce null check in IsDBNullAllowed implementation if (converter?.HandlesNulls != true && (forceNullCheck || (dataContext.IsDBNullAllowed(dataReader, idx) ?? true))) { ex = Condition( Call(dataReaderExpr, Methods.ADONet.IsDBNull, ExpressionInstances.Int32Array(idx)), Constant(mappingSchema.GetDefaultValue(type), type), ex); } return(ex); }