GetDataColumnBySchemaAction() private method

private GetDataColumnBySchemaAction ( DataTable dataTable, Type dataType, MissingSchemaAction schemaAction ) : DataColumn
dataTable DataTable
dataType Type
schemaAction MissingSchemaAction
return DataColumn
Beispiel #1
0
        public static DataColumn GetDataColumn(DataColumnMappingCollection columnMappings, string sourceColumn, Type dataType, DataTable dataTable, MissingMappingAction mappingAction, MissingSchemaAction schemaAction)
        {
            if (columnMappings != null)
            {
                int index = columnMappings.IndexOf(sourceColumn);
                if (-1 != index)
                {
                    return(columnMappings.items[index].GetDataColumnBySchemaAction(dataTable, dataType, schemaAction));
                }
            }
            if (ADP.IsEmpty(sourceColumn))
            {
                throw ADP.InvalidSourceColumn("sourceColumn");
            }
            switch (mappingAction)
            {
            case MissingMappingAction.Passthrough:
                return(DataColumnMapping.GetDataColumnBySchemaAction(sourceColumn, sourceColumn, dataTable, dataType, schemaAction));

            case MissingMappingAction.Ignore:
                return(null);

            case MissingMappingAction.Error:
                throw ADP.MissingColumnMapping(sourceColumn);
            }
            throw ADP.InvalidMissingMappingAction(mappingAction);
        }
 private DataColumn GetParameterDataColumn(String columnName, DataTableMapping mappings, DataRow row)
 {
     if (!ADP.IsEmpty(columnName))
     {
         DataColumnMapping columnMapping = mappings.GetColumnMappingBySchemaAction(columnName, this.missingMapping);
         if (null != columnMapping)
         {
             return(columnMapping.GetDataColumnBySchemaAction(row.Table, null, missingSchema));
         }
     }
     return(null);
 }
Beispiel #3
0
        public static DataColumn GetDataColumn(DataColumnMappingCollection columnMappings, string sourceColumn, Type dataType, DataTable dataTable, MissingMappingAction mappingAction, MissingSchemaAction schemaAction)
        {
            if (null != columnMappings)
            {
                int index = columnMappings.IndexOf(sourceColumn);
                if (-1 != index)
                {
#if DEBUG
                    if (AdapterSwitches.DataSchema.TraceInfo)
                    {
                        Debug.WriteLine($"mapping match on SourceColumn \"{sourceColumn}\"");
                    }
#endif
                    return(columnMappings._items[index].GetDataColumnBySchemaAction(dataTable, dataType, schemaAction));
                }
            }
            if (string.IsNullOrEmpty(sourceColumn))
            {
                throw ADP.InvalidSourceColumn(nameof(sourceColumn));
            }
            switch (mappingAction)
            {
            case MissingMappingAction.Passthrough:
#if DEBUG
                if (AdapterSwitches.DataSchema.TraceInfo)
                {
                    Debug.WriteLine($"mapping passthrough of SourceColumn \"{sourceColumn}\"");
                }
#endif
                return(DataColumnMapping.GetDataColumnBySchemaAction(sourceColumn, sourceColumn, dataTable, dataType, schemaAction));

            case MissingMappingAction.Ignore:
#if DEBUG
                if (AdapterSwitches.DataSchema.TraceWarning)
                {
                    Debug.WriteLine($"mapping filter of SourceColumn \"{sourceColumn}\"");
                }
#endif
                return(null);

            case MissingMappingAction.Error:
#if DEBUG
                if (AdapterSwitches.DataSchema.TraceError)
                {
                    Debug.WriteLine($"mapping error on SourceColumn \"{sourceColumn}\"");
                }
#endif
                throw ADP.MissingColumnMapping(sourceColumn);
            }
            throw ADP.InvalidMissingMappingAction(mappingAction);
        }
Beispiel #4
0
        /// <summary>
        ///     Creates or Modifies the schema of the given DataTable based on the schema of
        ///     the reader and the arguments passed.
        /// </summary>
        internal static int[] BuildSchema(IDataReader reader, DataTable table,
                                          SchemaType schemaType,
                                          MissingSchemaAction missingSchAction,
                                          MissingMappingAction missingMapAction,
                                          DataTableMappingCollection dtMapping
                                          )
        {
            int readerIndex = 0;

            // FIXME : this fails if query has fewer columns than a table
            int[] mapping = new int[table.Columns.Count];             // mapping the reader indexes to the datatable indexes

            for (int i = 0; i < mapping.Length; i++)
            {
                mapping[i] = -1;
            }

            ArrayList primaryKey       = new ArrayList();
            ArrayList sourceColumns    = new ArrayList();
            bool      createPrimaryKey = true;

            DataTable schemaTable = reader.GetSchemaTable();

            DataColumn ColumnNameCol      = schemaTable.Columns["ColumnName"];
            DataColumn DataTypeCol        = schemaTable.Columns["DataType"];
            DataColumn IsAutoIncrementCol = schemaTable.Columns["IsAutoIncrement"];
            DataColumn AllowDBNullCol     = schemaTable.Columns["AllowDBNull"];
            DataColumn IsReadOnlyCol      = schemaTable.Columns["IsReadOnly"];
            DataColumn IsKeyCol           = schemaTable.Columns["IsKey"];
            DataColumn IsUniqueCol        = schemaTable.Columns["IsUnique"];
            DataColumn ColumnSizeCol      = schemaTable.Columns["ColumnSize"];

            foreach (DataRow schemaRow in schemaTable.Rows)
            {
                // generate a unique column name in the source table.
                string sourceColumnName;
                string realSourceColumnName;
                if (ColumnNameCol == null || schemaRow.IsNull(ColumnNameCol) ||
                    (string)schemaRow [ColumnNameCol] == String.Empty)
                {
                    sourceColumnName     = DefaultSourceColumnName;
                    realSourceColumnName = DefaultSourceColumnName + "1";
                }
                else
                {
                    sourceColumnName     = (string)schemaRow [ColumnNameCol];
                    realSourceColumnName = sourceColumnName;
                }

                for (int i = 1; sourceColumns.Contains(realSourceColumnName); i += 1)
                {
                    realSourceColumnName = String.Format("{0}{1}", sourceColumnName, i);
                }
                sourceColumns.Add(realSourceColumnName);

                // generate DataSetColumnName from DataTableMapping, if any
                DataTableMapping tableMapping = null;

                //FIXME : The sourcetable name shud get passed as a parameter..
                int    index    = dtMapping.IndexOfDataSetTable(table.TableName);
                string srcTable = (index != -1 ? dtMapping[index].SourceTable : table.TableName);
                tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(dtMapping, ADP.IsEmpty(srcTable) ? " " : srcTable, table.TableName, missingMapAction);
                if (tableMapping != null)
                {
                    table.TableName = tableMapping.DataSetTable;
                    // check to see if the column mapping exists
                    DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction);
                    if (columnMapping != null)
                    {
                        Type       columnType = schemaRow[DataTypeCol] as Type;
                        DataColumn col        = columnType != null?columnMapping.GetDataColumnBySchemaAction(
                            table,
                            columnType,
                            missingSchAction) : null;

                        if (col != null)
                        {
                            // if the column is not in the table - add it.
                            if (table.Columns.IndexOf(col) == -1)
                            {
                                if (missingSchAction == MissingSchemaAction.Add ||
                                    missingSchAction == MissingSchemaAction.AddWithKey)
                                {
                                    table.Columns.Add(col);
                                }

                                int[] tmp = new int[mapping.Length + 1];
                                Array.Copy(mapping, 0, tmp, 0, col.Ordinal);
                                Array.Copy(mapping, col.Ordinal, tmp, col.Ordinal + 1, mapping.Length - col.Ordinal);
                                mapping = tmp;
                            }

                            if (missingSchAction == MissingSchemaAction.AddWithKey)
                            {
                                object value       = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null;
                                bool   allowDBNull = value is bool?(bool)value : true;

                                value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null;
                                bool isKey = value is bool?(bool)value : false;

                                value = (IsAutoIncrementCol != null) ? schemaRow[IsAutoIncrementCol] : null;
                                bool isAutoIncrement = value is bool?(bool)value : false;

                                value = (IsReadOnlyCol != null) ? schemaRow[IsReadOnlyCol] : null;
                                bool isReadOnly = value is bool?(bool)value : false;

                                value = (IsUniqueCol != null) ? schemaRow[IsUniqueCol] : null;
                                bool isUnique = value is bool?(bool)value : false;

                                col.AllowDBNull = allowDBNull;
                                // fill woth key info
                                if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType))
                                {
                                    col.AutoIncrement = true;
                                    if (!allowDBNull)
                                    {
                                        col.AllowDBNull = false;
                                    }
                                }

                                if (columnType == DbTypes.TypeOfString)
                                {
                                    col.MaxLength = (ColumnSizeCol != null) ? (int)schemaRow[ColumnSizeCol] : 0;
                                }

                                if (isReadOnly)
                                {
                                    col.ReadOnly = true;
                                }

                                if (!allowDBNull && (!isReadOnly || isKey))
                                {
                                    col.AllowDBNull = false;
                                }
                                if (isUnique && !isKey && !columnType.IsArray)
                                {
                                    col.Unique = true;
                                    if (!allowDBNull)
                                    {
                                        col.AllowDBNull = false;
                                    }
                                }

                                // This might not be set by all DataProviders
                                bool isHidden = false;
                                if (schemaTable.Columns.Contains("IsHidden"))
                                {
                                    value    = schemaRow["IsHidden"];
                                    isHidden = ((value is bool) ? (bool)value : false);
                                }

                                if (isKey && !isHidden)
                                {
                                    primaryKey.Add(col);
                                    if (allowDBNull)
                                    {
                                        createPrimaryKey = false;
                                    }
                                }
                            }
                            // add the ordinal of the column as a key and the index of the column in the datareader as a value.
                            mapping[col.Ordinal] = readerIndex++;
                        }
                    }
                }
            }
            if (primaryKey.Count > 0)
            {
                DataColumn[] colKey = (DataColumn[])(primaryKey.ToArray(typeof(DataColumn)));
                if (createPrimaryKey)
                {
                    table.PrimaryKey = colKey;
                }
                else
                {
                    UniqueConstraint uConstraint = new UniqueConstraint(colKey);
                    for (int i = 0; i < table.Constraints.Count; i++)
                    {
                        if (table.Constraints[i].Equals(uConstraint))
                        {
                            uConstraint = null;
                            break;
                        }
                    }

                    if (uConstraint != null)
                    {
                        table.Constraints.Add(uConstraint);
                    }
                }
            }
            return(mapping);
        }
        private void SetupSchemaWithKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, bool gettingData, DataColumn parentChapterColumn, object chapterValue)
        {
#if DEBUG
            Debug.Assert(null != schemaTable, "null schematable");
            if (AdapterSwitches.DataSchema.TraceVerbose)
            {
                ADP.TraceDataTable("SetupSchema", schemaTable);
            }
#endif
            DBSchemaRow[] schemaRows = DBSchemaRow.GetSortedSchemaRows(schemaTable); // MDAC 60609
            Debug.Assert(null != schemaRows, "SchemaSetup - null DBSchemaRow[]");

            int count = schemaRows.Length;
            if (0 == count)
            {
                this.dataTable = null;
                return;
            }

            bool         addPrimaryKeys = (0 == this.dataTable.PrimaryKey.Length); // MDAC 67033
            DataColumn[] keys           = null;
            int          keyCount       = 0;
            bool         isPrimary      = true; // assume key info (if any) is about a primary key

            int[]  columnIndexMap  = null;
            bool[] chapterIndexMap = null;

            int mappingCount = 0;
            GenerateFieldNames(count);

            DataColumnCollection columnCollection = null;
            for (int sortedIndex = 0; sortedIndex < count; ++sortedIndex)
            {
                DBSchemaRow schemaRow = schemaRows[sortedIndex];

                int unsortedIndex = schemaRow.UnsortedIndex; // MDAC 67050

                DataColumnMapping columnMapping = null;
                Type       fieldType            = schemaRow.DataType;
                DataColumn dataColumn           = null;

                if (!schemaRow.IsHidden)
                {
                    columnMapping = tableMapping.GetColumnMappingBySchemaAction(fieldNames[sortedIndex], mappingAction);
                }

                bool ischapter = false;
                if ((null != columnMapping) && typeof(IDataReader).IsAssignableFrom(fieldType))
                {
                    if (null == chapterIndexMap)
                    {
                        chapterIndexMap = new bool[count];
                    }
                    chapterIndexMap[unsortedIndex] = ischapter = true;

                    fieldType = typeof(Int32);
                }

                if (columnMapping != null)
                {
                    dataColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                }

                if (null == dataColumn)
                {
                    if (null == columnIndexMap)
                    {
                        columnIndexMap = CreateIndexMap(count, unsortedIndex);
                    }
                    columnIndexMap[unsortedIndex] = -1;

                    // if the column is not mapped and it is a key, then don't add any key information
                    if (schemaRow.IsKey)
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: partial primary key detected");
                        }
#endif
                        addPrimaryKeys = false; // don't add any future keys now
                        keys           = null;  // get rid of any keys we've seen
                    }
                    continue;                   // null means ignore (mapped to nothing)
                }

                if (ischapter)
                {
                    if (null == dataColumn.Table)
                    {
                        dataColumn.AllowDBNull   = false;
                        dataColumn.AutoIncrement = true;
                        dataColumn.ReadOnly      = true;
                    }
                    else if (!dataColumn.AutoIncrement)
                    {
                        throw ADP.FillChapterAutoIncrement();
                    }
                }
                else  // MDAC 67033
                {
                    if (schemaRow.IsAutoIncrement && IsAutoIncrementType(fieldType))
                    {
                        // CONSIDER: use T-SQL "IDENT_INCR('table_or_view')" and "IDENT_SEED('table_or_view')"
                        //           functions to obtain the actual increment and seed values
                        dataColumn.AutoIncrement = true;

                        if (!schemaRow.AllowDBNull)   // MDAC 71060
                        {
                            dataColumn.AllowDBNull = false;
                        }
                    }

                    // setup maxLength, only for string columns since this is all the DataSet supports
                    if (fieldType == typeof(string))
                    {
                        //@devnote:  schemaRow.Size is count of characters for string columns, count of bytes otherwise
                        dataColumn.MaxLength = schemaRow.Size;
                    }

                    if (schemaRow.IsReadOnly)
                    {
                        dataColumn.ReadOnly = true;
                    }
                    if (!schemaRow.AllowDBNull && (!schemaRow.IsReadOnly || schemaRow.IsKey))   // MDAC 71060, 72252
                    {
                        dataColumn.AllowDBNull = false;
                    }

                    if (schemaRow.IsUnique && !schemaRow.IsKey && !fieldType.IsArray)
                    {
                        // note, arrays are not comparable so only mark non-arrays as unique, ie timestamp columns
                        // are unique, but not comparable
                        dataColumn.Unique = true;

                        if (!schemaRow.AllowDBNull)   // MDAC 71060
                        {
                            dataColumn.AllowDBNull = false;
                        }
                    }
                }
                if (null == dataColumn.Table)
                {
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    columnCollection.Add(dataColumn);
                }

                // The server sends us one key per table according to these rules.
                //
                // 1. If the table has a primary key, the server sends us this key.
                // 2. If the table has a primary key and a unique key, it sends us the primary key
                // 3. if the table has no primary key but has a unique key, it sends us the unique key
                //
                // In case 3, we will promote a unique key to a primary key IFF all the columns that compose
                // that key are not nullable since no columns in a primary key can be null.  If one or more
                // of the keys is nullable, then we will add a unique constraint.
                //
                if (addPrimaryKeys && schemaRow.IsKey)   // MDAC 67033
                {
                    if (keys == null)
                    {
                        keys = new DataColumn[count];
                    }
                    keys[keyCount++] = dataColumn;
#if DEBUG
                    if (AdapterSwitches.DataSchema.TraceVerbose)
                    {
                        Debug.WriteLine("SetupSchema: building list of " + ((isPrimary) ? "PrimaryKey" : "UniqueConstraint"));
                    }
#endif
                    // see case 3 above, we do want dataColumn.AllowDBNull not schemaRow.AllowDBNull
                    // otherwise adding PrimaryKey will change AllowDBNull to false
                    if (isPrimary && dataColumn.AllowDBNull)   // MDAC 72241
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: changing PrimaryKey into UniqueContraint");
                        }
#endif
                        isPrimary = false;
                    }
                }

                if (null != columnIndexMap)
                {
                    columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                }
                else if (unsortedIndex != dataColumn.Ordinal)
                {
                    columnIndexMap = CreateIndexMap(count, unsortedIndex);
                    columnIndexMap[unsortedIndex] = dataColumn.Ordinal;
                }
                mappingCount++;
            }

            bool       addDataRelation = false;
            DataColumn chapterColumn   = null;
            if (null != chapterValue)   // add the extra column in the child table
            {
                DataColumnMapping columnMapping = tableMapping.GetColumnMappingBySchemaAction(tableMapping.SourceTable, mappingAction);
                if (null != columnMapping)
                {
                    Type fieldType = chapterValue.GetType();
                    chapterColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                    if (null != chapterColumn)
                    {
                        if (null == chapterColumn.Table)
                        {
                            chapterColumn.ReadOnly    = true; // MDAC 71878
                            chapterColumn.AllowDBNull = false;

                            if (null == columnCollection)
                            {
                                columnCollection = dataTable.Columns;
                            }
                            columnCollection.Add(chapterColumn);
                            addDataRelation = (null != parentChapterColumn);
                        }
                        mappingCount++;
                    }
                }
            }

            object[] dataValues = null;
            if (0 < mappingCount)
            {
                if ((null != this.dataSet) && null == this.dataTable.DataSet)
                {
                    this.dataSet.Tables.Add(this.dataTable);
                }
                // setup the key
                if (addPrimaryKeys && (null != keys))   // MDAC 67033
                {
                    if (keyCount < keys.Length)
                    {
                        keys = ResizeColumnArray(keys, keyCount);
                    }

                    // MDAC 66188
                    if (isPrimary)
                    {
#if DEBUG
                        if (AdapterSwitches.DataSchema.TraceVerbose)
                        {
                            Debug.WriteLine("SetupSchema: set_PrimaryKey");
                        }
#endif
                        this.dataTable.PrimaryKey = keys;
                    }
                    else
                    {
                        UniqueConstraint     unique      = new UniqueConstraint("", keys);
                        ConstraintCollection constraints = this.dataTable.Constraints;
                        int constraintCount = constraints.Count;
                        for (int i = 0; i < constraintCount; ++i)
                        {
                            if (unique.Equals(constraints[i]))
                            {
#if DEBUG
                                if (AdapterSwitches.DataSchema.TraceVerbose)
                                {
                                    Debug.WriteLine("SetupSchema: duplicate Contraint detected");
                                }
#endif
                                unique = null;
                                break;
                            }
                        }
                        if (null != unique)
                        {
#if DEBUG
                            if (AdapterSwitches.DataSchema.TraceVerbose)
                            {
                                Debug.WriteLine("SetupSchema: adding new UniqueConstraint");
                            }
#endif
                            constraints.Add(unique);
                        }
                    }
                }
                if (gettingData)
                {
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    _indexMap   = columnIndexMap;
                    _chapterMap = chapterIndexMap;
                    dataValues  = SetupMapping(count, columnCollection, chapterColumn, chapterValue);
                }
#if DEBUG
                else
                {
                    this.mappedMode = -1;
                }
#endif
            }
            else
            {
                this.dataTable = null;
            }
            if (addDataRelation)
            {
                AddRelation(parentChapterColumn, chapterColumn);
            }
            _readerDataValues = dataValues;
        }
        private void SetupSchemaWithoutKeyInfo(MissingMappingAction mappingAction, MissingSchemaAction schemaAction, bool gettingData, DataColumn parentChapterColumn, object chapterValue)
        {
            int[]  columnIndexMap  = null;
            bool[] chapterIndexMap = null;

            int mappingCount = 0;
            int count        = this.dataReader.FieldCount;

            GenerateFieldNames(count);

            DataColumnCollection columnCollection = null;

            for (int i = 0; i < count; ++i)
            {
                DataColumnMapping columnMapping = tableMapping.GetColumnMappingBySchemaAction(fieldNames[i], mappingAction);
                if (null == columnMapping)
                {
                    if (null == columnIndexMap)
                    {
                        columnIndexMap = CreateIndexMap(count, i);
                    }
                    columnIndexMap[i] = -1;
                    continue; // null means ignore (mapped to nothing)
                }

                bool ischapter = false;
                Type fieldType = this.dataReader.GetFieldType(i);
                if (typeof(IDataReader).IsAssignableFrom(fieldType))
                {
                    if (null == chapterIndexMap)
                    {
                        chapterIndexMap = new bool[count];
                    }
                    chapterIndexMap[i] = ischapter = true;

                    fieldType = typeof(Int32);
                }

                DataColumn dataColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                if (null == dataColumn)
                {
                    if (null == columnIndexMap)
                    {
                        columnIndexMap = CreateIndexMap(count, i);
                    }
                    columnIndexMap[i] = -1;
                    continue; // null means ignore (mapped to nothing)
                }

                if (null == dataColumn.Table)
                {
                    if (ischapter)
                    {
                        dataColumn.AllowDBNull   = false;
                        dataColumn.AutoIncrement = true;
                        dataColumn.ReadOnly      = true;
                    }
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    columnCollection.Add(dataColumn);
                }
                else if (ischapter && !dataColumn.AutoIncrement)
                {
                    throw ADP.FillChapterAutoIncrement();
                }

                if (null != columnIndexMap)
                {
                    columnIndexMap[i] = dataColumn.Ordinal;
                }
                else if (i != dataColumn.Ordinal)
                {
                    columnIndexMap    = CreateIndexMap(count, i);
                    columnIndexMap[i] = dataColumn.Ordinal;
                }
                mappingCount++;
            }

            bool       addDataRelation = false;
            DataColumn chapterColumn   = null;

            if (null != chapterValue)   // add the extra column in the child table
            {
                DataColumnMapping columnMapping = tableMapping.GetColumnMappingBySchemaAction(tableMapping.SourceTable, mappingAction);
                if (null != columnMapping)
                {
                    Type fieldType = chapterValue.GetType();
                    chapterColumn = columnMapping.GetDataColumnBySchemaAction(this.dataTable, fieldType, schemaAction);
                    if (null != chapterColumn)
                    {
                        if (null == chapterColumn.Table)
                        {
                            if (null == columnCollection)
                            {
                                columnCollection = dataTable.Columns;
                            }
                            columnCollection.Add(chapterColumn);
                            addDataRelation = (null != parentChapterColumn);
                        }
                        mappingCount++;
                    }
                }
            }

            object[] dataValues = null;
            if (0 < mappingCount)
            {
                if ((null != this.dataSet) && (null == this.dataTable.DataSet))
                {
                    // Allowed to throw exception if DataTable is from wrong DataSet
                    this.dataSet.Tables.Add(this.dataTable);
                }
                if (gettingData)
                {
                    if (null == columnCollection)
                    {
                        columnCollection = dataTable.Columns;
                    }
                    _indexMap   = columnIndexMap;
                    _chapterMap = chapterIndexMap;
                    dataValues  = SetupMapping(count, columnCollection, chapterColumn, chapterValue);
                }
#if DEBUG
                else
                {
                    this.mappedMode = -1;
                }
#endif
            }
            else
            {
                this.dataTable = null;
            }

            if (addDataRelation)
            {
                AddRelation(parentChapterColumn, chapterColumn);
            }
            _readerDataValues = dataValues;
        }