コード例 #1
0
            public object GetRawValueSequential(IDataReader dataReader, Type[] forTypes)
            {
                var fromType = dataReader.GetFieldType(ColumnIndex);

                if (!_slowRawReaders.TryGetValue(fromType, out var func))
                {
                    var dataReaderParameter = Parameter(typeof(IDataReader));
                    var dataReaderExpr      = Convert(dataReaderParameter, dataReader.GetType());

                    MethodCallExpression rawExpr = null !;
                    foreach (var type in forTypes)
                    {
                        var expr           = GetColumnReader(_dataContext, _mappingSchema, dataReader, type, _converter, ColumnIndex, dataReaderExpr, _slowMode);
                        var currentRawExpr = SequentialAccessHelper.ExtractRawValueReader(expr, ColumnIndex);

                        if (rawExpr == null)
                        {
                            rawExpr = currentRawExpr;
                        }
                        else if (rawExpr.Method != currentRawExpr.Method)
                        {
                            throw new LinqToDBConvertException(
                                      $"Different data reader methods used for same column: '{rawExpr.Method.DeclaringType?.Name}.{rawExpr.Method.Name}' vs '{currentRawExpr.Method.DeclaringType?.Name}.{currentRawExpr.Method.Name}'");
                        }
                    }

                    var lex = Lambda <Func <IDataReader, object> >(
                        rawExpr.Type == typeof(object) ? rawExpr : Convert(rawExpr, typeof(object)),
                        dataReaderParameter);

                    _slowRawReaders[fromType] = func = lex.CompileExpression();
                }

                return(func(dataReader));
            }
コード例 #2
0
        public Func <IDataReader, T> BuildReaderFunction <T>()
        {
            var expr = BuildReaderExpression();

            var lambda = Expression.Lambda <Func <IDataReader, T> >(BuildBlock(expr), DataReaderParam);

            if (Common.Configuration.OptimizeForSequentialAccess)
            {
                lambda = (Expression <Func <IDataReader, T> >)SequentialAccessHelper.OptimizeMappingExpressionForSequentialAccess(lambda, Reader.FieldCount, reduce: true);
            }

            return(lambda.Compile());
        }
コード例 #3
0
            /*
             * We could have column readers for same column with different ColumnType types  which results in different
             * reader expressions.
             * To make it work with sequential mode we should perform actual column value read from reader only
             * once and then use it in reader expressions for all types.
             * For that we add additional method to read raw value and then pass it to GetValueSequential.
             * We need extra method as we cannot store raw value in field: ColumnReader instance could be used
             * from multiple threads, so it cannot have state. For same reason it doesn't make much sense to reduce number
             * of ColumnReader instances in mapper expression to one for single column. It could be done later if we will
             * see benefits of it, but frankly speaking it doesn't make sense to optimize slow-mode reader.
             *
             * Limitation is the same as for non-slow mapper:
             * column mapping expressions should use same reader method to get column value. This limitation enforced
             * in GetRawValueSequential method.
             */
            public object?GetValueSequential(IDataReader dataReader, bool isNull, object?rawValue)
            {
                var fromType = dataReader.GetFieldType(ColumnIndex);

                if (!_slowColumnConverters.TryGetValue(fromType, out var func))
                {
                    var dataReaderParameter = Parameter(typeof(IDataReader));
                    var isNullParameter     = Parameter(typeof(bool));
                    var rawValueParameter   = Parameter(typeof(object));
                    var dataReaderExpr      = Convert(dataReaderParameter, dataReader.GetType());

                    var expr = GetColumnReader(_dataContext, _mappingSchema, dataReader, ColumnType, _converter, ColumnIndex, dataReaderExpr, _slowMode);
                    expr = SequentialAccessHelper.OptimizeColumnReaderForSequentialAccess(expr, isNullParameter, rawValueParameter, ColumnIndex);

                    var lex = Lambda <Func <bool, object?, object?> >(
                        expr.Type == typeof(object) ? expr : Convert(expr, typeof(object)),
                        isNullParameter,
                        rawValueParameter);

                    _slowColumnConverters[fromType] = func = lex.CompileExpression();
                }

                try
                {
                    return(func(isNull, rawValue));
                }
                catch (LinqToDBConvertException ex)
                {
                    ex.ColumnName = dataReader.GetName(ColumnIndex);
                    throw;
                }
                catch (Exception ex)
                {
                    var name = dataReader.GetName(ColumnIndex);
                    throw new LinqToDBConvertException(
                              $"Mapping of column '{name}' value failed, see inner exception for details", ex)
                          {
                              ColumnName = name
                          };
                }
            }