/// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public override IRelationalValueBufferFactory CreateValueBufferFactory(
            IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
        {
            Check.NotNull(relationalValueBufferFactoryFactory, nameof(relationalValueBufferFactoryFactory));
            Check.NotNull(dataReader, nameof(dataReader));

            var readerColumns
                = Enumerable
                  .Range(0, dataReader.FieldCount)
                  .Select(
                      i => new
            {
                Name    = dataReader.GetName(i),
                Ordinal = i
            })
                  .ToList();

            var types = new TypeMaterializationInfo[SelectExpression.Projection.Count];

            for (var i = 0; i < SelectExpression.Projection.Count; i++)
            {
                if (SelectExpression.Projection[i] is ColumnExpression columnExpression)
                {
                    var columnName = columnExpression.Name;

                    if (columnName != null)
                    {
                        var readerColumn
                            = readerColumns.SingleOrDefault(
                                  c =>
                                  string.Equals(columnName, c.Name, StringComparison.OrdinalIgnoreCase));

                        if (readerColumn == null)
                        {
                            throw new InvalidOperationException(RelationalStrings.FromSqlMissingColumn(columnName));
                        }

                        types[i] = new TypeMaterializationInfo(
                            columnExpression.Type,
                            columnExpression.Property,
                            Dependencies.TypeMappingSource,
                            fromLeftOuterJoin: false,
                            readerColumn.Ordinal);
                    }
                }
            }

            return(relationalValueBufferFactoryFactory.Create(types));
        }
Exemple #2
0
        private static Expression CreateGetValueExpression(
            Expression dataReaderExpression,
            int index,
            TypeMaterializationInfo materializationInfo,
            bool detailedErrorsEnabled,
            bool box = true)
        {
            var getMethod = materializationInfo.Mapping.GetDataReaderMethod();

            index = materializationInfo.Index == -1 ? index : materializationInfo.Index;

            var indexExpression = Expression.Constant(index);

            Expression valueExpression
                = Expression.Call(
                      getMethod.DeclaringType != typeof(DbDataReader)
                        ? Expression.Convert(dataReaderExpression, getMethod.DeclaringType)
                        : dataReaderExpression,
                      getMethod,
                      indexExpression);

            valueExpression = materializationInfo.Mapping.CustomizeDataReaderExpression(valueExpression);

            var converter = materializationInfo.Mapping.Converter;

            if (converter != null)
            {
                if (valueExpression.Type != converter.ProviderClrType)
                {
                    valueExpression = Expression.Convert(valueExpression, converter.ProviderClrType);
                }

                valueExpression = ReplacingExpressionVisitor.Replace(
                    converter.ConvertFromProviderExpression.Parameters.Single(),
                    valueExpression,
                    converter.ConvertFromProviderExpression.Body);
            }

            if (valueExpression.Type != materializationInfo.ModelClrType)
            {
                valueExpression = Expression.Convert(valueExpression, materializationInfo.ModelClrType);
            }

            var exceptionParameter
                = Expression.Parameter(typeof(Exception), name: "e");

            var property = materializationInfo.Property;

            if (detailedErrorsEnabled)
            {
                var catchBlock
                    = Expression
                      .Catch(
                          exceptionParameter,
                          Expression.Call(
                              _throwReadValueExceptionMethod
                              .MakeGenericMethod(valueExpression.Type),
                              exceptionParameter,
                              Expression.Call(
                                  dataReaderExpression,
                                  _getFieldValueMethod.MakeGenericMethod(typeof(object)),
                                  indexExpression),
                              Expression.Constant(property, typeof(IPropertyBase))));

                valueExpression = Expression.TryCatch(valueExpression, catchBlock);
            }

            if (box && valueExpression.Type.GetTypeInfo().IsValueType)
            {
                valueExpression = Expression.Convert(valueExpression, typeof(object));
            }

            if (property?.IsNullable != false ||
                property.DeclaringEntityType.BaseType != null ||
                materializationInfo.IsFromLeftOuterJoin != false)
            {
                valueExpression
                    = Expression.Condition(
                          Expression.Call(dataReaderExpression, _isDbNullMethod, indexExpression),
                          Expression.Default(valueExpression.Type),
                          valueExpression);
            }

            return(valueExpression);
        }
Exemple #3
0
 /// <summary>
 ///     Determines whether the specified object is equal to the current object.
 /// </summary>
 /// <param name="other">The object to compare with the current object.</param>
 /// <returns><see langword="true" /> if the specified object is equal to the current object; otherwise, <see langword="false" />.</returns>
 protected virtual bool Equals(TypeMaterializationInfo other)
 => ProviderClrType == other.ProviderClrType &&
 ModelClrType == other.ModelClrType &&
 Equals(Mapping, other.Mapping) &&
 Equals(Property, other.Property) &&
 IsNullable == other.IsNullable;