public Action <MappingSchema, NpgsqlBinaryImporter, ColumnDescriptor[], TEntity> CreateBinaryImportRowWriter <TEntity>( PostgreSQLDataProvider provider, BasicSqlBuilder sqlBuilder, ColumnDescriptor[] columns, MappingSchema mappingSchema) { var generator = new ExpressionGenerator(_typeMapper); var pMapping = Expression.Parameter(typeof(MappingSchema)); var pWriterIn = Expression.Parameter(typeof(NpgsqlBinaryImporter)); var pColumns = Expression.Parameter(typeof(ColumnDescriptor[])); var pEntity = Expression.Parameter(typeof(TEntity)); var pWriter = generator.AddVariable(Expression.Parameter(_npgsqlBinaryImporterType)); generator.Assign(pWriter, Expression.Convert(ExpressionHelper.Property(pWriterIn, nameof(TypeWrapper.instance_)), _npgsqlBinaryImporterType)); generator.AddExpression(generator.MapAction((NpgsqlBinaryImporter importer) => importer.StartRow(), pWriter)); for (var i = 0; i < columns.Length; i++) { var npgsqlType = provider.GetNativeType(columns[i].DbType, true); if (npgsqlType == null) { var columnType = columns[i].DataType != DataType.Undefined ? new SqlDataType(columns[i]) : null; if (columnType == null || columnType.Type.DataType == DataType.Undefined) { columnType = mappingSchema.GetDataType(columns[i].StorageType); } var sb = new StringBuilder(); sqlBuilder.BuildTypeName(sb, columnType); npgsqlType = provider.GetNativeType(sb.ToString(), true); } if (npgsqlType == null) { throw new LinqToDBException($"Cannot guess PostgreSQL type for column {columns[i].ColumnName}. Specify type explicitly in column mapping."); } // don't use WriteNull because Write already handle both null and DBNull values properly // also use object as type parameter, as it is not important for npgsql now generator.AddExpression( Expression.Call( pWriter, "Write", new[] { typeof(object) }, //columns[idx].GetValue(mappingSchema, entity) Expression.Call(Expression.ArrayIndex(pColumns, Expression.Constant(i)), "GetValue", Array <Type> .Empty, pMapping, pEntity), Expression.Convert(Expression.Constant(npgsqlType.Value), _dbTypeType))); } var ex = Expression.Lambda <Action <MappingSchema, NpgsqlBinaryImporter, ColumnDescriptor[], TEntity> >( generator.Build(), pMapping, pWriterIn, pColumns, pEntity); return(ex.Compile()); }
Expression BuildExpression(int fieldIndex, ISqlExpression?sqlExpression) { Expression expr; if (SequenceHelper.UnwrapSubqueryContext(Sequence) is DefaultIfEmptyBuilder.DefaultIfEmptyContext defaultIfEmpty) { expr = Builder.BuildSql(_returnType, fieldIndex, sqlExpression); if (defaultIfEmpty.DefaultValue != null && expr is ConvertFromDataReaderExpression convert) { var generator = new ExpressionGenerator(); expr = convert.MakeNullable(); if (expr.Type.IsNullable()) { var exprVar = generator.AssignToVariable(expr, "nullable"); var defaultValue = defaultIfEmpty.DefaultValue; if (defaultValue.Type != expr.Type) { var convertLambda = Builder.MappingSchema.GenerateSafeConvert(defaultValue.Type, expr.Type); defaultValue = InternalExtensions.ApplyLambdaToExpression(convertLambda, defaultValue); } var resultVar = generator.AssignToVariable(defaultValue, "result"); generator.AddExpression(Expression.IfThen( Expression.NotEqual(exprVar, ExpressionInstances.UntypedNull), Expression.Assign(resultVar, Expression.Convert(exprVar, resultVar.Type)))); generator.AddExpression(resultVar); expr = generator.Build(); } } } else if (_methodName == "Sum" || _returnType.IsNullableType()) { expr = Builder.BuildSql(_returnType, fieldIndex, sqlExpression); } else { expr = Expression.Block( Expression.Call(null, MemberHelper.MethodOf(() => CheckNullValue(false, null !)), Expression.Call(ExpressionBuilder.DataReaderParam, Methods.ADONet.IsDBNull, ExpressionInstances.Constant0), Expression.Constant(_methodName)), Builder.BuildSql(_returnType, fieldIndex, sqlExpression)); } return(expr); }
public void Setup() { var typeMapper = new TypeMapper(); typeMapper.RegisterTypeWrapper <Wrapped.NpgsqlBinaryImporter>(typeof(Original.NpgsqlBinaryImporter)); typeMapper.RegisterTypeWrapper <Wrapped.NpgsqlDbType>(typeof(Original.NpgsqlDbType)); typeMapper.FinalizeMappings(); _wrappedImporter = typeMapper.Wrap <Wrapped.NpgsqlBinaryImporter>(_originalImporter); var ed = MappingSchema.GetEntityDescriptor(typeof(TestEntity)); _columns = ed.Columns.ToArray(); var generator = new ExpressionGenerator(typeMapper); var pMapping = Expression.Parameter(typeof(MappingSchema)); var pWriterIn = Expression.Parameter(typeof(Wrapped.NpgsqlBinaryImporter)); var pColumns = Expression.Parameter(typeof(ColumnDescriptor[])); var pEntity = Expression.Parameter(typeof(TestEntity)); var pWriter = generator.AddVariable(Expression.Parameter(typeof(Original.NpgsqlBinaryImporter))); generator.Assign(pWriter, Expression.Convert(Expression.PropertyOrField(pWriterIn, "instance_"), typeof(Original.NpgsqlBinaryImporter))); generator.AddExpression(generator.MapAction((Wrapped.NpgsqlBinaryImporter importer) => importer.StartRow(), pWriter)); for (var i = 0; i < _columns.Length; i++) { generator.AddExpression( Expression.Call( pWriter, "Write", new[] { typeof(object) }, Expression.Call(Expression.ArrayIndex(pColumns, Expression.Constant(i)), "GetValue", Array <Type> .Empty, pEntity), Expression.Convert(Expression.Constant(Wrapped.NpgsqlDbType.Test), typeof(Original.NpgsqlDbType)))); } _rowWriter = Expression.Lambda <Action <MappingSchema, Wrapped.NpgsqlBinaryImporter, ColumnDescriptor[], TestEntity> >( generator.Build(), pMapping, pWriterIn, pColumns, pEntity) .Compile(); }
Expression BuildExpression(int fieldIndex, ISqlExpression?sqlExpression) { Expression expr; if (Sequence is DefaultIfEmptyBuilder.DefaultIfEmptyContext defaultIfEmpty) { expr = Builder.BuildSql(_returnType, fieldIndex, sqlExpression); if (defaultIfEmpty.DefaultValue != null && expr is ConvertFromDataReaderExpression convert) { var generator = new ExpressionGenerator(); expr = convert.MakeNullable(); if (expr.Type.IsNullable()) { var exprVar = generator.AssignToVariable(expr, "nullable"); var resultVar = generator.AssignToVariable(defaultIfEmpty.DefaultValue, "result"); generator.AddExpression(Expression.IfThen( Expression.NotEqual(exprVar, Expression.Constant(null)), Expression.Assign(resultVar, Expression.Convert(exprVar, resultVar.Type)))); generator.AddExpression(resultVar); expr = generator.Build(); } } } else if (_returnType.IsClass || _methodName == "Sum" || _returnType.IsNullable()) { expr = Builder.BuildSql(_returnType, fieldIndex, sqlExpression); } else { expr = Expression.Block( Expression.Call(null, MemberHelper.MethodOf(() => CheckNullValue(false, null !)), Expression.Call(ExpressionBuilder.DataReaderParam, Methods.ADONet.IsDBNull, Expression.Constant(0)), Expression.Constant(_methodName)), Builder.BuildSql(_returnType, fieldIndex, sqlExpression)); } return(expr); }
public Func<double> Compile(Block block) { ParameterExpression result = Expression.Parameter(typeof(int), "result"); var compiler = new ExpressionGenerator(); compiler.SetReturnType<double>(); foreach (var varDef in block.Variables.Values) { //var v = Expression.Variable(ExpressionCompiler.GetCsType(varDef.ValueType), varDef.Name.Name); //expressions.Add(v); compiler.AddVariable(varDef); } foreach (var statement in block.Statements) { compiler.AddExpression(statement); } BlockExpression blockExpression = compiler.Generate(); var lambda = Expression.Lambda<Func<double>>(blockExpression); var compiled = lambda.Compile(); return compiled; }
private static OracleProviderAdapter CreateAdapter(string assemblyName, string clientNamespace, string typesNamespace, string?factoryName) { var isNative = false; #if NETFRAMEWORK isNative = assemblyName == NativeAssemblyName; #endif var assembly = Common.Tools.TryLoadAssembly(assemblyName, factoryName); if (assembly == null) { throw new InvalidOperationException($"Cannot load assembly {assemblyName}"); } var connectionType = assembly.GetType($"{clientNamespace}.OracleConnection", true) !; var parameterType = assembly.GetType($"{clientNamespace}.OracleParameter", true) !; var dataReaderType = assembly.GetType($"{clientNamespace}.OracleDataReader", true) !; var transactionType = assembly.GetType($"{clientNamespace}.OracleTransaction", true) !; var dbType = assembly.GetType($"{clientNamespace}.OracleDbType", true) !; var commandType = assembly.GetType($"{clientNamespace}.OracleCommand", true) !; var mappingSchema = new MappingSchema(); // do not set default conversion for BFile as it could be converted to file name, byte[], Stream and we don't know what user needs var oracleBFileType = loadType("OracleBFile", DataType.BFile, skipConvertExpression: true) !; var oracleBinaryType = loadType("OracleBinary", DataType.VarBinary) !; var oracleBlobType = loadType("OracleBlob", DataType.Blob) !; var oracleClobType = loadType("OracleClob", DataType.NText) !; var oracleDateType = loadType("OracleDate", DataType.DateTime) !; var oracleDecimalType = loadType("OracleDecimal", DataType.Decimal) !; var oracleIntervalDSType = loadType("OracleIntervalDS", DataType.Time) !; var oracleIntervalYMType = loadType("OracleIntervalYM", DataType.Date) !; var oracleStringType = loadType("OracleString", DataType.NVarChar) !; var oracleTimeStampType = loadType("OracleTimeStamp", DataType.DateTime2) !; var oracleTimeStampLTZType = loadType("OracleTimeStampLTZ", DataType.DateTimeOffset) !; var oracleTimeStampTZType = loadType("OracleTimeStampTZ", DataType.DateTimeOffset) !; var oracleXmlTypeType = loadType("OracleXmlType", DataType.Xml) !; var oracleXmlStreamType = loadType("OracleXmlStream", DataType.Xml, true, false) !; var oracleRefCursorType = loadType("OracleRefCursor", DataType.Binary, hasValue: false) !; var oracleRefType = loadType("OracleRef", DataType.Binary, true); BulkCopyAdapter?bulkCopy = null; var typeMapper = new TypeMapper(); typeMapper.RegisterTypeWrapper <OracleConnection>(connectionType); typeMapper.RegisterTypeWrapper <OracleParameter>(parameterType); typeMapper.RegisterTypeWrapper <OracleDbType>(dbType); typeMapper.RegisterTypeWrapper <OracleCommand>(commandType); typeMapper.RegisterTypeWrapper <OracleDataReader>(dataReaderType); typeMapper.RegisterTypeWrapper <OracleTimeStampTZ>(oracleTimeStampTZType); typeMapper.RegisterTypeWrapper <OracleTimeStampLTZ>(oracleTimeStampLTZType); typeMapper.RegisterTypeWrapper <OracleDecimal>(oracleDecimalType); if (isNative) { var bulkCopyType = assembly.GetType($"{clientNamespace}.OracleBulkCopy", true) !; var bulkCopyOptionsType = assembly.GetType($"{clientNamespace}.OracleBulkCopyOptions", true) !; var bulkRowsCopiedEventHandlerType = assembly.GetType($"{clientNamespace}.OracleRowsCopiedEventHandler", true) !; var bulkCopyColumnMappingType = assembly.GetType($"{clientNamespace}.OracleBulkCopyColumnMapping", true) !; var bulkCopyColumnMappingCollectionType = assembly.GetType($"{clientNamespace}.OracleBulkCopyColumnMappingCollection", true) !; var rowsCopiedEventArgsType = assembly.GetType($"{clientNamespace}.OracleRowsCopiedEventArgs", true) !; // bulk copy types typeMapper.RegisterTypeWrapper <OracleBulkCopy>(bulkCopyType); typeMapper.RegisterTypeWrapper <OracleBulkCopyOptions>(bulkCopyOptionsType); typeMapper.RegisterTypeWrapper <OracleRowsCopiedEventHandler>(bulkRowsCopiedEventHandlerType); typeMapper.RegisterTypeWrapper <OracleBulkCopyColumnMapping>(bulkCopyColumnMappingType); typeMapper.RegisterTypeWrapper <OracleBulkCopyColumnMappingCollection>(bulkCopyColumnMappingCollectionType); typeMapper.RegisterTypeWrapper <OracleRowsCopiedEventArgs>(rowsCopiedEventArgsType); typeMapper.FinalizeMappings(); bulkCopy = new BulkCopyAdapter( typeMapper.BuildWrappedFactory((IDbConnection connection, OracleBulkCopyOptions options) => new OracleBulkCopy((OracleConnection)connection, options)), typeMapper.BuildWrappedFactory((int source, string destination) => new OracleBulkCopyColumnMapping(source, destination))); } else { typeMapper.FinalizeMappings(); } var paramMapper = typeMapper.Type <OracleParameter>(); var dbTypeBuilder = paramMapper.Member(p => p.OracleDbType); var connectionMapper = typeMapper.Type <OracleConnection>(); var commandMapper = typeMapper.Type <OracleCommand>(); // data reader expressions // rd.GetOracleTimeStampTZ(i) => DateTimeOffset var generator = new ExpressionGenerator(typeMapper); var rdParam = Expression.Parameter(typeof(IDataReader), "rd"); var indexParam = Expression.Parameter(typeof(int), "i"); var tstzExpr = generator.MapExpression((IDataReader rd, int i) => ((OracleDataReader)rd).GetOracleTimeStampTZ(i), rdParam, indexParam); var tstzVariable = generator.AssignToVariable(tstzExpr, "tstz"); var expr = generator.MapExpression((OracleTimeStampTZ tstz) => new DateTimeOffset( tstz.Year, tstz.Month, tstz.Day, tstz.Hour, tstz.Minute, tstz.Second, tstz.GetTimeZoneOffset()).AddTicks(tstz.Nanosecond / NanosecondsPerTick), tstzVariable); generator.AddExpression(expr); var body = generator.Build(); var readDateTimeOffsetFromOracleTimeStampTZ = (Expression <Func <IDataReader, int, DateTimeOffset> >)Expression.Lambda(body, rdParam, indexParam); // rd.GetOracleTimeStampLTZ(i) => DateTimeOffset generator = new ExpressionGenerator(typeMapper); tstzExpr = generator.MapExpression((IDataReader rd, int i) => ((OracleDataReader)rd).GetOracleTimeStampLTZ(i).ToOracleTimeStampTZ(), rdParam, indexParam); tstzVariable = generator.AssignToVariable(tstzExpr, "tstz"); expr = generator.MapExpression((OracleTimeStampTZ tstz) => new DateTimeOffset( tstz.Year, tstz.Month, tstz.Day, tstz.Hour, tstz.Minute, tstz.Second, tstz.GetTimeZoneOffset()).AddTicks(tstz.Nanosecond / NanosecondsPerTick), tstzVariable); generator.AddExpression(expr); body = generator.Build(); var readDateTimeOffsetFromOracleTimeStampLTZ = (Expression <Func <IDataReader, int, DateTimeOffset> >)Expression.Lambda(body, rdParam, indexParam); // rd.GetOracleDecimal(i) => decimal generator = new ExpressionGenerator(typeMapper); var decExpr = generator.MapExpression((IDataReader rd, int i) => ((OracleDataReader)rd).GetOracleDecimal(i), rdParam, indexParam); var oracleDecimalVar = generator.AssignToVariable(decExpr, "dec"); var precision = generator.AssignToVariable(Expression.Constant(29), "precision"); var decimalVar = generator.AddVariable(Expression.Parameter(typeof(decimal), "dec")); var label = Expression.Label(typeof(decimal)); generator.AddExpression( Expression.Loop( Expression.TryCatch( Expression.Block( Expression.Assign(oracleDecimalVar, generator.MapExpression((OracleDecimal d, int p) => OracleDecimal.SetPrecision(d, p), oracleDecimalVar, precision)), Expression.Assign(decimalVar, Expression.Convert(oracleDecimalVar, typeof(decimal))), Expression.Break(label, decimalVar)), Expression.Catch( typeof(OverflowException), Expression.Block( Expression.IfThen( Expression.LessThanOrEqual(Expression.SubtractAssign(precision, Expression.Constant(1)), Expression.Constant(26)), Expression.Rethrow())))), label)); body = generator.Build(); var readOracleDecimalToDecimalAdv = (Expression <Func <IDataReader, int, decimal> >)Expression.Lambda(body, rdParam, indexParam); // workaround for mapper issue with complex reader expressions handling // https://github.com/linq2db/linq2db/issues/2032 var compiledReader = readOracleDecimalToDecimalAdv.Compile(); readOracleDecimalToDecimalAdv = (Expression <Func <IDataReader, int, decimal> >)Expression.Lambda( Expression.Invoke(Expression.Constant(compiledReader), rdParam, indexParam), rdParam, indexParam); var readOracleDecimalToInt = (Expression <Func <IDataReader, int, int> >)typeMapper.MapLambda <IDataReader, int, int>((rd, i) => (int)(decimal)OracleDecimal.SetPrecision(((OracleDataReader)rd).GetOracleDecimal(i), 27)); var readOracleDecimalToLong = (Expression <Func <IDataReader, int, long> >)typeMapper.MapLambda <IDataReader, int, long>((rd, i) => (long)(decimal)OracleDecimal.SetPrecision(((OracleDataReader)rd).GetOracleDecimal(i), 27)); var readOracleDecimalToDecimal = (Expression <Func <IDataReader, int, decimal> >)typeMapper.MapLambda <IDataReader, int, decimal>((rd, i) => (decimal)OracleDecimal.SetPrecision(((OracleDataReader)rd).GetOracleDecimal(i), 27)); return(new OracleProviderAdapter( connectionType, dataReaderType, parameterType, commandType, transactionType, mappingSchema, oracleBFileType, oracleBinaryType, oracleBlobType, oracleClobType, oracleDateType, oracleDecimalType, oracleIntervalDSType, oracleIntervalYMType, oracleStringType, oracleTimeStampType, oracleTimeStampLTZType, oracleTimeStampTZType, oracleXmlTypeType, oracleXmlStreamType, oracleRefCursorType, oracleRefType, typeMapper.BuildWrappedFactory((string connectionString) => new OracleConnection(connectionString)), typesNamespace, dbTypeBuilder.BuildSetter <IDbDataParameter>(), dbTypeBuilder.BuildGetter <IDbDataParameter>(), connectionMapper.Member(c => c.HostName).BuildGetter <IDbConnection>(), connectionMapper.Member(c => c.DatabaseName).BuildGetter <IDbConnection>(), commandMapper.Member(p => p.BindByName).BuildSetter <IDbCommand>(), commandMapper.Member(p => p.ArrayBindCount).BuildSetter <IDbCommand>(), commandMapper.Member(p => p.InitialLONGFetchSize).BuildSetter <IDbCommand>(), typeMapper.BuildFactory((DateTimeOffset dto, string offset) => new OracleTimeStampTZ(dto.Year, dto.Month, dto.Day, dto.Hour, dto.Minute, dto.Second, GetDateTimeOffsetNanoseconds(dto), offset)), readDateTimeOffsetFromOracleTimeStampTZ, readDateTimeOffsetFromOracleTimeStampLTZ, readOracleDecimalToDecimalAdv, readOracleDecimalToInt, readOracleDecimalToLong, readOracleDecimalToDecimal, bulkCopy)); Type?loadType(string typeName, DataType dataType, bool optional = false, bool hasNull = true, bool hasValue = true, bool skipConvertExpression = false) { var type = assembly !.GetType($"{typesNamespace}.{typeName}", !optional); if (type == null) { return(null); } if (hasNull) { // if native provider fails here, check that you have ODAC installed properly var getNullValue = Expression.Lambda <Func <object> >(Expression.Convert(ExpressionHelper.Field(type, "Null"), typeof(object))).Compile(); mappingSchema.AddScalarType(type, getNullValue(), true, dataType); } else { mappingSchema.AddScalarType(type, null, true, dataType); } if (skipConvertExpression) { return(type); } // conversion from provider-specific type var valueParam = Expression.Parameter(type); Expression memberExpression; if (!hasValue) { memberExpression = valueParam; } else { memberExpression = ExpressionHelper.Property(valueParam, "Value"); } var condition = Expression.Condition( Expression.Equal(valueParam, ExpressionHelper.Field(type, "Null")), Expression.Constant(null, typeof(object)), Expression.Convert(memberExpression, typeof(object))); var convertExpression = Expression.Lambda(condition, valueParam); mappingSchema.SetConvertExpression(type, typeof(object), convertExpression); return(type); } }
public void Setup() { var typeMapper = new TypeMapper(); typeMapper.RegisterTypeWrapper <Wrapped.OracleDataReader>(typeof(Original.OracleDataReader)); typeMapper.RegisterTypeWrapper <Wrapped.OracleTimeStampTZ>(typeof(Original.OracleTimeStampTZ)); typeMapper.RegisterTypeWrapper <Wrapped.OracleTimeStampLTZ>(typeof(Original.OracleTimeStampLTZ)); typeMapper.RegisterTypeWrapper <Wrapped.OracleDecimal>(typeof(Original.OracleDecimal)); typeMapper.FinalizeMappings(); // _readDateTimeOffsetFromOracleTimeStampTZ var generator = new ExpressionGenerator(typeMapper); var rdParam = Expression.Parameter(typeof(ITestDataReader), "rd"); var indexParam = Expression.Parameter(typeof(int), "i"); var tstzExpr = generator.MapExpression((ITestDataReader rd, int i) => ((Wrapped.OracleDataReader)rd).GetOracleTimeStampTZ(i), rdParam, indexParam); var tstzVariable = generator.AssignToVariable(tstzExpr, "tstz"); var expr = generator.MapExpression((Wrapped.OracleTimeStampTZ tstz) => new DateTimeOffset( tstz.Year, tstz.Month, tstz.Day, tstz.Hour, tstz.Minute, tstz.Second, tstz.GetTimeZoneOffset()).AddTicks(tstz.Nanosecond / NanosecondsPerTick), tstzVariable); generator.AddExpression(expr); var body = generator.Build(); _readDateTimeOffsetFromOracleTimeStampTZ = ((Expression <Func <ITestDataReader, int, DateTimeOffset> >)Expression.Lambda(body, rdParam, indexParam)).Compile(); // _readDateTimeOffsetFromOracleTimeStampLTZ generator = new ExpressionGenerator(typeMapper); tstzExpr = generator.MapExpression((ITestDataReader rd, int i) => ((Wrapped.OracleDataReader)rd).GetOracleTimeStampLTZ(i).ToOracleTimeStampTZ(), rdParam, indexParam); tstzVariable = generator.AssignToVariable(tstzExpr, "tstz"); expr = generator.MapExpression((Wrapped.OracleTimeStampTZ tstz) => new DateTimeOffset( tstz.Year, tstz.Month, tstz.Day, tstz.Hour, tstz.Minute, tstz.Second, tstz.GetTimeZoneOffset()).AddTicks(tstz.Nanosecond / NanosecondsPerTick), tstzVariable); generator.AddExpression(expr); body = generator.Build(); _readDateTimeOffsetFromOracleTimeStampLTZ = ((Expression <Func <ITestDataReader, int, DateTimeOffset> >)Expression.Lambda(body, rdParam, indexParam)).Compile(); // rd.GetOracleDecimal(i) => decimal generator = new ExpressionGenerator(typeMapper); var decExpr = generator.MapExpression((ITestDataReader rd, int i) => ((Wrapped.OracleDataReader)rd).GetOracleDecimal(i), rdParam, indexParam); var oracleDecimalVar = generator.AssignToVariable(decExpr, "dec"); var precision = generator.AssignToVariable(Expression.Constant(29), "precision"); var decimalVar = generator.AddVariable(Expression.Parameter(typeof(decimal), "dec")); var label = Expression.Label(typeof(decimal)); generator.AddExpression( Expression.Loop( Expression.TryCatch( Expression.Block( Expression.Assign(oracleDecimalVar, generator.MapExpression((Wrapped.OracleDecimal d, int p) => Wrapped.OracleDecimal.SetPrecision(d, p), oracleDecimalVar, precision)), Expression.Assign(decimalVar, Expression.Convert(oracleDecimalVar, typeof(decimal))), Expression.Break(label, decimalVar)), Expression.Catch( typeof(OverflowException), Expression.Block( Expression.IfThen( Expression.LessThanOrEqual(Expression.SubtractAssign(precision, Expression.Constant(1)), Expression.Constant(26)), Expression.Rethrow())))), label)); body = generator.Build(); var readOracleDecimalToDecimalAdv = (Expression <Func <ITestDataReader, int, decimal> >)Expression.Lambda(body, rdParam, indexParam); // workaround for mapper issue with complex reader expressions handling // https://github.com/linq2db/linq2db/issues/2032 var compiledReader = readOracleDecimalToDecimalAdv.Compile(); _readOracleDecimalToDecimalAdv = ((Expression <Func <ITestDataReader, int, decimal> >)Expression.Lambda( Expression.Invoke(Expression.Constant(compiledReader), rdParam, indexParam), rdParam, indexParam)).Compile(); _readOracleDecimalToInt = ((Expression <Func <ITestDataReader, int, int> >)typeMapper.MapLambda <ITestDataReader, int, int>((rd, i) => (int)(decimal)Wrapped.OracleDecimal.SetPrecision(((Wrapped.OracleDataReader)rd).GetOracleDecimal(i), 27))).Compile(); _readOracleDecimalToLong = ((Expression <Func <ITestDataReader, int, long> >)typeMapper.MapLambda <ITestDataReader, int, long>((rd, i) => (long)(decimal)Wrapped.OracleDecimal.SetPrecision(((Wrapped.OracleDataReader)rd).GetOracleDecimal(i), 27))).Compile(); _readOracleDecimalToDecimal = ((Expression <Func <ITestDataReader, int, decimal> >)typeMapper.MapLambda <ITestDataReader, int, decimal>((rd, i) => (decimal)Wrapped.OracleDecimal.SetPrecision(((Wrapped.OracleDataReader)rd).GetOracleDecimal(i), 27))).Compile(); }