public Expression Reduce(IDataContext dataContext, bool slowMode) { var columnReader = new ColumnReader(dataContext, dataContext.MappingSchema, _type, _idx, Converter, slowMode); if (slowMode && Configuration.OptimizeForSequentialAccess) { return(Convert(Call(Constant(columnReader), Methods.LinqToDB.ColumnReader.GetValueSequential, _dataReaderParam, Call(_dataReaderParam, Methods.ADONet.IsDBNull, ExpressionInstances.Int32Array(_idx)), Call(Methods.LinqToDB.ColumnReader.RawValuePlaceholder)), _type)); } else { return(Convert(Call(Constant(columnReader), Methods.LinqToDB.ColumnReader.GetValue, _dataReaderParam), _type)); } }
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); }
private void Path <T>(IEnumerable <T> source, PropertyInfo property) where T : Expression { var prop = Expression.Property(_path, property); var i = 0; foreach (var item in source) { _path = Expression.Call(prop, ReflectionHelper.IndexExpressor <T> .Item, ExpressionInstances.Int32Array(i++)); Path(item); } }