System.Data.XmlDataLoader.LoadTable C# (CSharp) Method

LoadTable() private method

private LoadTable ( DataTable table, bool isNested ) : void
table DataTable
isNested bool
return void
        private void LoadTable(DataTable table, bool isNested)
        {
            //  <DataSet> /--------------------------- We are here on entrance
            //      <Table>               
            //          <Column>Value</Column>
            //          <AnotherColumn>Value</AnotherColumn>
            //      </Table>    /-------------------------- We are here on exit           
            //      <AnotherTable>
            //      ...
            //      </AnotherTable>
            //      ...
            //  </DataSet> 

            Debug.Assert(table != null, "Table to be loaded is null on LoadTable() entry");

            DataRow row = null;                                 // Data row we're going to add to this table

            int entryDepth = _dataReader.Depth;                  // Store current reader depth so we know when to stop reading
            int entryChild = _childRowsStack.Count;              // Memorize child stack level on entry

            DataColumn c;                                       // Hold column here
            DataColumnCollection collection = table.Columns;    // Hold column collectio here

            object[] foundColumns = new object[collection.Count];
            // This is the columns data we found 
            // This is used to process diffgramms

            int rowOrder = -1;                                  // Row to insert data to
            string diffId = string.Empty;                       // Diffgram ID string
            string hasChanges = null;                           // Changes string
            bool hasErrors = false;                             // Set this in case of problem

            string textNodeValue;                               // Value of a text node we might have

            // Process attributes first                         

            for (int i = _dataReader.AttributeCount - 1; i >= 0; --i)
            {
                // Check all attributes one by one
                _dataReader.MoveToAttribute(i);                  // Get this attribute

                c = _nodeToSchemaMap.GetColumnSchema(table, _dataReader, FIgnoreNamespace(_dataReader)) as DataColumn;
                // Try to get column for this attribute

                if ((c != null) && (c.ColumnMapping == MappingType.Attribute))
                {
                    // Yep, it is a column mapped as attribute
                    // Get value from XML and store it in the object array
                    foundColumns[c.Ordinal] = c.ConvertXmlToObject(_dataReader.Value);
                }                                               // Oops. No column for this element

                if (_isDiffgram)
                {                             // Now handle some diffgram attributes 
                    if (_dataReader.NamespaceURI == Keywords.DFFNS)
                    {
                        switch (_dataReader.LocalName)
                        {
                            case Keywords.DIFFID:                   // Is it a diffgeam ID ?
                                diffId = _dataReader.Value;          // Store ID
                                break;
                            case Keywords.HASCHANGES:               // Has chages attribute ?
                                hasChanges = _dataReader.Value;      // Store value
                                break;
                            case Keywords.HASERRORS:                // Has errors attribute ?
                                hasErrors = (bool)Convert.ChangeType(_dataReader.Value, typeof(bool), CultureInfo.InvariantCulture);
                                // Store value
                                break;
                        }
                    }
                    else if (_dataReader.NamespaceURI == Keywords.MSDNS)
                    {
                        if (_dataReader.LocalName == Keywords.ROWORDER)
                        {
                            // Is it a row order attribute ?
                            rowOrder = (int)Convert.ChangeType(_dataReader.Value, typeof(int), CultureInfo.InvariantCulture);
                            // Store it
                        }
                        else if (_dataReader.LocalName.StartsWith("hidden", StringComparison.Ordinal))
                        {
                            // Hidden column ?
                            c = collection[XmlConvert.DecodeName(_dataReader.LocalName.Substring(6))];
                            // Let's see if we have one. 
                            // We have to decode name before we look it up
                            // We could not use XmlToDataSet map as it contains
                            // no hidden columns
                            if ((c != null) && (c.ColumnMapping == MappingType.Hidden))
                            {
                                // Got column and it is hidden ?
                                foundColumns[c.Ordinal] = c.ConvertXmlToObject(_dataReader.Value);
                            }
                        }
                    }
                }
            }                                                   // Done with attributes

            // Now handle elements. This could be columns or nested tables.

            //  <DataSet> /------------------- We are here after dealing with attributes
            //      <Table foo="FooValue" bar="BarValue">  
            //          <Column>Value</Column>
            //          <AnotherColumn>Value</AnotherColumn>
            //      </Table>
            //  </DataSet>

            if (_dataReader.Read() && entryDepth < _dataReader.Depth)
            {
                // Read to the next element and see if we're inside
                while (entryDepth < _dataReader.Depth)
                {       // Get out as soon as we've processed all nested nodes.
                    switch (_dataReader.NodeType)
                    {              // Process nodes based on type
                        case XmlNodeType.Element:                   // It's an element
                            object o = _nodeToSchemaMap.GetColumnSchema(table, _dataReader, FIgnoreNamespace(_dataReader));
                            // Get dataset element for this XML element
                            c = o as DataColumn;                    // Perhaps, it's a column?

                            if (c != null)
                            {                      // Do we have matched column in this table?
                                                   // Let's load column data
                                if (foundColumns[c.Ordinal] == null)
                                {
                                    // If this column was not found before
                                    LoadColumn(c, foundColumns);
                                    // Get column value
                                }
                                else
                                {
                                    _dataReader.Read();              // Advance to next element. 
                                }
                            }
                            else
                            {
                                DataTable nestedTable = o as DataTable;
                                // Perhaps, it's a nested table ?
                                if (nestedTable != null)
                                {        // Do we have matched nested table in DataSet ?
                                    LoadTable(nestedTable, true /* isNested */);
                                    // Yes. Load nested table (recursive)
                                }                                   // Not a table nor column? Check if it's schema.
                                else if (ProcessXsdSchema())
                                {      // Check for schema. Skip or load if found.
                                    continue;                       // Schema has been found. Process the next element 
                                                                    // we're already at (done by schema processing).
                                }
                                else
                                {
                                    // We've got element which is not supposed to he here according to the schema.
                                    // That might be a table which was misplaced. We should've thrown on that, 
                                    // but we'll try to load it so we could keep compatibility.
                                    // We won't try to match to columns as we have no idea 
                                    // which table this potential column might belong to.
                                    DataTable misplacedTable = _nodeToSchemaMap.GetTableForNode(_dataReader, FIgnoreNamespace(_dataReader));
                                    // Try to get table for node

                                    if (misplacedTable != null)
                                    {   // Got some matching table?
                                        LoadTable(misplacedTable, false /* isNested */);
                                        // While table's XML element is nested,
                                        // the table itself is not. Load it this way.
                                    }
                                    else
                                    {
                                        _dataReader.Read();          // Not a table? Try next element.
                                    }
                                }
                            }
                            break;
                        case XmlNodeType.EntityReference:           // Oops. No support for Entity Reference
                            throw ExceptionBuilder.FoundEntity();
                        case XmlNodeType.Text:                      // It looks like a text.
                        case XmlNodeType.Whitespace:                // This actually could be
                        case XmlNodeType.CDATA:                     // if we have XmlText in our table
                        case XmlNodeType.SignificantWhitespace:
                            textNodeValue = _dataReader.ReadString();
                            // Get text node value.
                            c = table._xmlText;                      // Get XML Text column from our table

                            if (c != null && foundColumns[c.Ordinal] == null)
                            {
                                // If XmlText Column is set
                                // and we do not have data already                
                                foundColumns[c.Ordinal] = c.ConvertXmlToObject(textNodeValue);
                                // Read and store the data
                            }
                            break;
                        default:
                            _dataReader.Read();                  // We don't process that, skip to the next element.
                            break;
                    }
                }

                _dataReader.Read();                              // We're done here, proceed to the next element.
            }

            // It's the time to populate row with loaded data and add it to the table we'we just read to the table

            if (_isDiffgram)
            {                               // In case of diffgram
                row = table.NewRow(table.NewUninitializedRecord());
                // just create an empty row
                row.BeginEdit();                            // and allow it's population with data 

                for (int i = foundColumns.Length - 1; i >= 0; --i)
                {
                    // Check all columns
                    c = collection[i];                      // Get column for this index

                    c[row._tempRecord] = null != foundColumns[i] ? foundColumns[i] : DBNull.Value;
                    // Set column to loaded value of to
                    // DBNull if value is missing.
                }

                row.EndEdit();                              // Done with this row

                table.Rows.DiffInsertAt(row, rowOrder);     // insert data to specific location

                // And do some diff processing
                if (hasChanges == null)
                {                   // No changes ?
                    row._oldRecord = row._newRecord;          // Restore old record
                }

                if ((hasChanges == Keywords.MODIFIED) || hasErrors)
                {
                    table.RowDiffId[diffId] = row;
                }
            }
            else
            {
                for (int i = foundColumns.Length - 1; i >= 0; --i)
                {
                    // Check all columns
                    if (null == foundColumns[i])
                    {          // Got data for this column ?
                        c = collection[i];                  // No. Get column for this index

                        if (c.AllowDBNull && c.ColumnMapping != MappingType.Hidden && !c.AutoIncrement)
                        {
                            foundColumns[i] = DBNull.Value; // Assign DBNull if possible
                                                            // table.Rows.Add() below will deal
                                                            // with default values and autoincrement
                        }
                    }
                }

                row = table.Rows.AddWithColumnEvents(foundColumns);         // Create, populate and add row
            }

            // Data is loaded into the row and row is added to the table at this point

            while (entryChild < _childRowsStack.Count)
            {     // Process child rows we might have
                DataRow childRow = (DataRow)_childRowsStack.Pop();
                // Get row from the stack
                bool unchanged = (childRow.RowState == DataRowState.Unchanged);
                // Is data the same as before?
                childRow.SetNestedParentRow(row, /*setNonNested*/ false);
                // Set parent row

                if (unchanged)                              // Restore record if child row's unchanged
                    childRow._oldRecord = childRow._newRecord;
            }

            if (isNested)                                   // Got parent ?
                _childRowsStack.Push(row);                   // Push row to the stack
        }