コード例 #1
0
    public StreamingObjectConstructor(DbDataReader source, ConstructorMetadata?constructor, IReadOnlyList <ColumnMetadata> nonNullableColumns, MaterializerTypeConverter converter)
    {
        m_Converter       = converter ?? new();
        m_Source          = source;
        m_Ordinals        = new Dictionary <string, int>(source.FieldCount, StringComparer.OrdinalIgnoreCase);
        m_NullableColumns = new Dictionary <int, bool>(source.FieldCount);
        for (var i = 0; i < source.FieldCount; i++)
        {
            var columnName = source.GetName(i);
            m_Ordinals.Add(columnName, i);
            m_NullableColumns.Add(i, !nonNullableColumns.Any(c => c.SqlName == columnName));             //assume nullable unless proven otherwise
        }

        if (constructor == null)
        {
            constructor = MetadataCache.GetMetadata(typeof(T)).Constructors.Find(s_DefaultConstructor);
        }
        if (constructor == null)
        {
            throw new MappingException($"Cannot find a default constructor for {typeof(T).Name}");
        }

        var desiredType = typeof(T);

        m_Constructor = constructor;

        var constructorParameters = m_Constructor.ParameterNames;

        for (var i = 0; i < constructorParameters.Length; i++)
        {
            if (!m_Ordinals.ContainsKey(constructorParameters[i]))
            {
                throw new MappingException($"Cannot find a column that matches the parameter {constructorParameters[i]}");
            }
        }

        m_Dictionary = new StreamingObjectConstructorDictionary(this);

        if (constructor.Signature.Length == 0)
        {
            m_MappedProperties = new List <OrdinalMappedProperty <T> >();

            foreach (var mapper in s_AllMappedProperties)
            {
                if (m_Dictionary.ContainsKey(mapper.MappedColumnName))
                {
                    m_MappedProperties.Add(new OrdinalMappedProperty <T>(mapper, m_Ordinals[mapper.MappedColumnName]));
                }
            }
        }
    }
コード例 #2
0
    /// <summary>
    /// Creates a new Table from an IDataReader
    /// </summary>
    /// <param name="source">The source.</param>
    /// <exception cref="ArgumentNullException">nameof(s - rce), "source is</exception>
    /// <exception cref="ArgumentException">No columns were returned - source</exception>
    /// <param name="converter">The type converter.</param>
    public Table(DbDataReader source, MaterializerTypeConverter converter)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source), $"{nameof(source)} is null.");
        }
        if (source.FieldCount == 0)
        {
            throw new ArgumentException("No columns were returned", nameof(source));
        }

        m_Converter = converter ?? new();

        TableName = "";

        var cols     = new List <string>(source.FieldCount);
        var colTypes = new Dictionary <string, Type>(source.FieldCount, StringComparer.OrdinalIgnoreCase);

        for (var i = 0; i < source.FieldCount; i++)
        {
            cols.Add(source.GetName(i));
            colTypes.Add(source.GetName(i), source.GetFieldType(i));
        }
        m_Columns     = new ReadOnlyCollection <string>(cols);
        m_ColumnTypes = new ReadOnlyDictionary <string, Type>(colTypes);

        var rows = new Collection <Row>();

        while (source.Read())
        {
            var row = new Dictionary <string, object?>(source.FieldCount, StringComparer.OrdinalIgnoreCase);
            for (var i = 0; i < source.FieldCount; i++)
            {
                object?temp = source[i];
                if (temp == DBNull.Value)
                {
                    temp = null;
                }

                row.Add(source.GetName(i), temp);
            }

            rows.Add(new Row(row));
        }

        m_Rows = new RowCollection(rows);
    }
コード例 #3
0
ファイル: TableSet.cs プロジェクト: docevaad/Chain
    /// <summary>
    /// Initializes a new instance of the <see cref="TableSet" /> class.
    /// </summary>
    /// <param name="reader">The data reader used to populate this TableSet.</param>
    /// <param name="converter">The type converter.</param>
    /// <param name="tableNames">Optional list of table names.</param>
    /// <exception cref="System.ArgumentNullException">reader</exception>
    public TableSet(DbDataReader reader, MaterializerTypeConverter converter, params string[] tableNames)
    {
        if (reader == null)
        {
            throw new ArgumentNullException(nameof(reader), $"{nameof(reader)} is null.");
        }
        if (tableNames == null)
        {
            tableNames = Array.Empty <string>();
        }

        var index = 0;

        do
        {
            var tableName = (index < tableNames.Length) ? tableNames[index] : ("Table " + index);
            m_Internal.Add(new Table(tableName, reader, converter));
            index += 1;
        }while (reader.NextResult());
    }
コード例 #4
0
 /// <summary>
 /// Creates a new NamedTable from an IDataReader
 /// </summary>
 /// <param name="tableName">Name of the table.</param>
 /// <param name="source">The source.</param>
 /// <param name="converter">The type converter.</param>
 public Table(string tableName, DbDataReader source, MaterializerTypeConverter converter)
     : this(source, converter)
 {
     TableName = tableName;
 }
コード例 #5
0
        static object?SetProperty <T>(T target, PropertyMetadata property, object?value, OrdinalMappedProperty <T>?mapper, MaterializerTypeConverter converter)
            where T : class
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target), $"{nameof(target)} is null.");
            }

            if (property == null)
            {
                throw new ArgumentNullException(nameof(property), $"{nameof(property)} is null.");
            }

            var targetType = property.PropertyType;

            if (value != null && targetType != value.GetType())
            {
                if (!converter.TryConvertType(targetType, ref value, out var conversionException))
                {
                    throw new MappingException($"Cannot map value of type {value!.GetType().FullName} to property {property.Name} of type {targetType.Name}.", conversionException);
                }
            }

            if (mapper == null || value == null)
            {
                property.InvokeSet(target, value);
            }
            else
            {
                mapper.InvokeSet(target, value);
            }

            return(value);
        }
コード例 #6
0
        static void SetDecomposedProperty(IReadOnlyDictionary <string, object?> source, object target, string?decompositionPrefix, PropertyMetadata property, MaterializerTypeConverter converter)
        {
            object?child = null;

            if (property.CanRead)
            {
                child = property.InvokeGet(target);
            }

            if (child == null && property.CanWrite && property.PropertyType.GetConstructor(Array.Empty <Type>()) != null)
            {
                child = Activator.CreateInstance(property.PropertyType);
                property.InvokeSet(target, child);
            }

            if (child != null)
            {
                PopulateComplexObject(source, child, decompositionPrefix + property.DecompositionPrefix, converter);
            }
        }
コード例 #7
0
        static internal void PopulateComplexObject <T>(IReadOnlyDictionary <int, object?> source, T target, string?decompositionPrefix, IList <OrdinalMappedProperty <T> > mappedProperties, IList <MappedProperty <T> > decomposedProperties, MaterializerTypeConverter converter)
            where T : class
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source), $"{nameof(source)} is null.");
            }
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target), $"{nameof(target)} is null.");
            }

            foreach (var property in mappedProperties)
            {
                var value = source[property.Ordinal];

                SetProperty(target, property.PropertyMetadata, value, property, converter);
            }

            foreach (var property in decomposedProperties)
            {
                SetDecomposedProperty((IReadOnlyDictionary <string, object?>)source, target, decompositionPrefix, property.PropertyMetadata, converter);
            }
        }
コード例 #8
0
        static internal void PopulateComplexObject <T>(IReadOnlyDictionary <string, object?> source, T target, string?decompositionPrefix, MaterializerTypeConverter converter)
            where T : class
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source), $"{nameof(source)} is null.");
            }
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target), $"{nameof(target)} is null.");
            }

            foreach (var property in MetadataCache.GetMetadata(target.GetType()).Properties)
            {
                string mappedColumnName = decompositionPrefix + property.MappedColumnName;
                if (property.CanWrite && source.ContainsKey(mappedColumnName))
                {
                    var value = source[mappedColumnName];

                    value = SetProperty(target, property, value, null, converter);
                }
                else if (property.Decompose)
                {
                    SetDecomposedProperty(source, target, decompositionPrefix, property, converter);
                }
            }
        }
コード例 #9
0
        static internal T ConstructObject <T>(IReadOnlyDictionary <string, object?> source, ConstructorMetadata?constructor, MaterializerTypeConverter converter, bool?populateComplexObject = null)
            where T : class
        {
            //If we didn't get a constructor, look for a default constructor to use.
            if (constructor == null)
            {
                constructor = MetadataCache.GetMetadata(typeof(T)).Constructors.Find(s_EmptyTypeList);
            }
            if (constructor == null)
            {
                throw new MappingException($"Cannot find a default constructor for {typeof(T).Name}");
            }

            //populate properties when using a default constructor
            if (!populateComplexObject.HasValue)
            {
                populateComplexObject = constructor.Signature.Length == 0;
            }

            //Make sure we have all of the requested parameters
            var constructorParameters = constructor.ParameterNames;

            for (var i = 0; i < constructorParameters.Length; i++)
            {
                if (!source.ContainsKey(constructorParameters[i]))
                {
                    throw new MappingException($"Cannot find a column that matches the parameter {constructorParameters[i]}");
                }
            }

            //Build the constructor
            var parameters = new object?[constructorParameters.Length];

            for (var i = 0; i < constructorParameters.Length; i++)
            {
                parameters[i] = source[constructorParameters[i]];
            }
            var result = (T)constructor.ConstructorInfo.Invoke(parameters);

            if (populateComplexObject.Value)             //Populate properties and child objects
            {
                PopulateComplexObject(source, result, null, converter);
            }

            //Change tracking objects should be materialized as unchanged.
            (result as IChangeTracking)?.AcceptChanges();

            return(result);
        }
コード例 #10
0
 internal static StreamingObjectConstructor <T> AsObjectConstructor <T>(this DbDataReader reader, IReadOnlyList <Type>?constructorSignature, IReadOnlyList <ColumnMetadata> nonNullableColumns, MaterializerTypeConverter converter)
     where T : class
 {
     return(new StreamingObjectConstructor <T>(reader, constructorSignature, nonNullableColumns, converter));
 }