private static void SetParentProperties(this DbDataReader odr, object obj, ColumnParentMap childMap)
        {
            PropertyInfo pInfo = obj.GetType().GetProperty(childMap.PropInfo.Name);

            if (pInfo != null && pInfo.CanWrite && pInfo.ReflectedType.FullName == childMap.PropInfo.ReflectedType.FullName)
            {
                object childObj = pInfo.CanRead && pInfo.PropertyType.IsClass ? pInfo.GetValue(obj) : null;

                if (childObj == null)
                {
                    childObj = Activator.CreateInstance(pInfo.PropertyType);
                }

                odr.GetMappedParentObject(childObj, childMap.Children);

                childMap.SetMethod.Invoke(obj, new object[] { childObj });
            }
        }
        private static IEnumerable <ColumnMap> BuildColumnMaps(
            Type tType,
            OrdinalColumnMap[] keys,
            ColumnMapBuilderState state,
            IColumnMapSetting settings)
        {
            state.ProcessedTypes.Add(tType);
            PropertyInfo[] props          = tType.GetProperties(_bindingFlagInstancePublic);
            int            joinStartIndex = state.HasJoins ? GetJoinStartIndex(tType, keys, settings) : 0;


            for (int i = 0; i < props.Length; i++)
            {
                var p = props[i];

                if (state.MappedCount == state.NonExcludedCount)
                {
                    break;
                }

                if (p.CanWrite && p.GetCustomAttribute <NotMappedAttribute>() == null)
                {
                    Type propertyType       = p.PropertyType;
                    Type nullUnderlyingType = Nullable.GetUnderlyingType(propertyType);

                    if (
                        state.HasJoins &&
                        settings.Joins.ContainsKey(propertyType) &&
                        !state.ProcessedTypes.Contains(propertyType) &&
                        !_directTypeMap.Contains(propertyType) &&
                        ((propertyType.IsClass && propertyType.GetConstructor(Type.EmptyTypes) != null) || (propertyType.IsValueType && !(propertyType.IsEnum || (nullUnderlyingType?.IsEnum ?? false)))) &&
                        !propertyType.IsArray &&
                        !typeof(IEnumerable).IsAssignableFrom(propertyType) &&
                        !typeof(IListSource).IsAssignableFrom(propertyType)
                        )
                    {
                        var childrenMaps = BuildColumnMaps
                                           (
                            propertyType,
                            keys,
                            state,
                            settings
                                           ).OrderBy(m => m.Column.Ordinal).ToArray();

                        if (childrenMaps.Length > 0)
                        {
                            var parentMap = new ColumnParentMap
                            {
                                SetMethod = p.GetSetMethod(false),
                                PropInfo  = p,
                                Children  = childrenMaps
                            };

                            yield return(new ColumnMap {
                                Column = childrenMaps[0].Column, ParentMap = parentMap
                            });
                        }

                        continue;
                    }


                    string propColName = p.GetColumnAttributeName();

                    if (state.HasAliases && settings.Aliases.TryGetValue(tType, out Dictionary <string, string> aliasMap))
                    {
                        if (aliasMap != null && aliasMap.TryGetValue(propColName, out string alias))
                        {
                            propColName = alias;
                        }
                    }


                    var keyIndex = Array.FindIndex(keys, joinStartIndex, c => !c.IsMapped && c.Name == propColName);

                    if (keyIndex >= 0)
                    {
                        var  ordinalMap     = keys[keyIndex];
                        Type underlyingType = (nullUnderlyingType ?? propertyType);

                        ThrowIfFailedToMatchColumnTypeByNames(ordinalMap.FieldType, underlyingType, ordinalMap.Name, p.Name);


                        yield return(new ColumnMap
                        {
                            UnderlyingType = underlyingType,
                            SetMethod = p.GetSetMethod(false),
                            PropInfo = p,
                            Column = ordinalMap
                        });


                        ordinalMap.IsMapped = true;
                        state.MappedCount++;
                    }
#if DEBUG
                    else
                    {
                        Debug.WriteLine("Column name " + propColName + " not found in column schema for property " + propertyType + " of object " + tType);
                    }
#endif
                }
            }
        }