XmlToDatasetMap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / XmlToDatasetMap.cs / 1305376 / XmlToDatasetMap.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

namespace System.Data { 
    using System;
    using System.Xml;
    using System.Collections;
    using System.Diagnostics; 
    using System.Globalization;
 
    // This is an internal helper class used during Xml load to DataSet/DataDocument. 
    // XmlToDatasetMap class provides functionality for binding elemants/atributes
    // to DataTable / DataColumn 
    internal sealed class XmlToDatasetMap {

        private sealed class XmlNodeIdentety {
            public string LocalName; 
            public string NamespaceURI;
            public XmlNodeIdentety(string localName, string namespaceURI) { 
                this.LocalName    = localName; 
                this.NamespaceURI = namespaceURI;
            } 
            override public int GetHashCode() {
                return ((object) LocalName).GetHashCode();
            }
            override public bool Equals(object obj) { 
                XmlNodeIdentety id = (XmlNodeIdentety) obj;
                return ( 
                  (String.Compare(this.LocalName, id.LocalName, StringComparison.OrdinalIgnoreCase) == 0) && 
                  (String.Compare(this.NamespaceURI, id.NamespaceURI, StringComparison.OrdinalIgnoreCase) == 0)
                ); 
            }
        }

        // This class exist to avoid alocatin of XmlNodeIdentety to every acces to the hash table. 
        // Unfortunetely XmlNode doesn't export single identety object.
        internal sealed class XmlNodeIdHashtable : Hashtable { 
            private XmlNodeIdentety id = new XmlNodeIdentety(string.Empty, string.Empty); 
            public XmlNodeIdHashtable(Int32 capacity)
                : base(capacity) {} 
            public object this[XmlNode node] {
                get {
                    id.LocalName    = node.LocalName;
                    id.NamespaceURI = node.NamespaceURI; 
                    return this[id];
                } 
            } 

            public object this[XmlReader dataReader] { 
                get {
                    id.LocalName    = dataReader.LocalName;
                    id.NamespaceURI = dataReader.NamespaceURI;
                    return this[id]; 
                }
            } 
 
            public object this[DataTable table] {
                get { 
                    id.LocalName    = table.EncodedTableName;
                    id.NamespaceURI = table.Namespace;
                    return this[id];
                } 
            }
 
            public object this[string name] { 
                get {
                    id.LocalName    = name; 
                    id.NamespaceURI = String.Empty;
                    return this[id];
                }
            } 
        }
 
        private sealed class TableSchemaInfo { 
            public DataTable          TableSchema;
            public XmlNodeIdHashtable ColumnsSchemaMap; 
            public TableSchemaInfo(DataTable tableSchema) {
                this.TableSchema      = tableSchema;
                this.ColumnsSchemaMap = new XmlNodeIdHashtable(tableSchema.Columns.Count);
            } 
        }
 
        XmlNodeIdHashtable tableSchemaMap;              // Holds all the tables information 

        TableSchemaInfo lastTableSchemaInfo = null; 

        // Used to infer schema

        public XmlToDatasetMap(DataSet dataSet, XmlNameTable nameTable) { 
            Debug.Assert(dataSet   != null, "DataSet can't be null");
            Debug.Assert(nameTable != null, "NameTable can't be null"); 
            BuildIdentityMap(dataSet, nameTable); 
        }
 
        // Used to read data with known schema

        public XmlToDatasetMap(XmlNameTable nameTable, DataSet dataSet) {
            Debug.Assert(dataSet   != null, "DataSet can't be null"); 
            Debug.Assert(nameTable != null, "NameTable can't be null");
            BuildIdentityMap(nameTable, dataSet); 
        } 

        // Used to infer schema 

        public XmlToDatasetMap(DataTable dataTable, XmlNameTable nameTable) {
            Debug.Assert(dataTable != null, "DataTable can't be null");
            Debug.Assert(nameTable != null, "NameTable can't be null"); 
            BuildIdentityMap(dataTable, nameTable);
        } 
 
        // Used to read data with known schema
 
        public XmlToDatasetMap(XmlNameTable nameTable, DataTable dataTable) {
            Debug.Assert(dataTable  != null, "DataTable can't be null");
            Debug.Assert(nameTable != null, "NameTable can't be null");
            BuildIdentityMap(nameTable, dataTable); 
        }
        static internal bool IsMappedColumn(DataColumn c) { 
            return (c.ColumnMapping != MappingType.Hidden); 
        }
 
        // Used to infere schema

        private TableSchemaInfo AddTableSchema(DataTable table, XmlNameTable nameTable) {
            // [....]: Because in our case reader already read the document all names that we can meet in the 
            //       document already has an entry in NameTable.
            //       If in future we will build identity map before reading XML we can replace Get() to Add() 
            // [....]: GetIdentity is called from two places: BuildIdentityMap() and LoadRows() 
            //       First case deals with decoded names; Second one with encoded names.
            //       We decided encoded names in first case (instead of decoding them in second) 
            //       because it save us time in LoadRows(). We have, as usual, more data them schemas
            string tableLocalName = nameTable.Get(table.EncodedTableName);
            string tableNamespace = nameTable.Get(table.Namespace );
            if(tableLocalName == null) { 
                // because name of this table isn't present in XML we don't need mapping for it.
                // Less mapping faster we work. 
                return null; 
            }
            TableSchemaInfo tableSchemaInfo = new TableSchemaInfo(table); 
            tableSchemaMap[new XmlNodeIdentety(tableLocalName, tableNamespace)] = tableSchemaInfo;
            return tableSchemaInfo;
        }
 
        private TableSchemaInfo AddTableSchema(XmlNameTable nameTable, DataTable table) {
            // [....]:This is the opposite of the previous function: 
            //       we populate the nametable so that the hash comparison can happen as 
            //       object comparison instead of strings.
            // [....]: GetIdentity is called from two places: BuildIdentityMap() and LoadRows() 
            //       First case deals with decoded names; Second one with encoded names.
            //       We decided encoded names in first case (instead of decoding them in second)
            //       because it save us time in LoadRows(). We have, as usual, more data them schemas
 
            string _tableLocalName = table.EncodedTableName;            // Table name
 
            string tableLocalName = nameTable.Get(_tableLocalName);     // Look it up in nametable 

            if(tableLocalName == null) {                                // If not found 
                tableLocalName = nameTable.Add(_tableLocalName);        // Add it
            }

            table.encodedTableName = tableLocalName;                    // And set it back 

            string tableNamespace = nameTable.Get(table.Namespace);     // Look ip table namespace 
 
            if (tableNamespace == null) {                               // If not found
                tableNamespace = nameTable.Add(table.Namespace);        // Add it 
            }
            else {
                if (table.tableNamespace != null)                       // Update table namespace
                    table.tableNamespace = tableNamespace; 
            }
 
 
            TableSchemaInfo tableSchemaInfo = new TableSchemaInfo(table);
                                                                        // Create new table schema info 
            tableSchemaMap[new XmlNodeIdentety(tableLocalName, tableNamespace)] = tableSchemaInfo;
                                                                        // And add it to the hashtable
            return tableSchemaInfo;                                     // Return it as we have to populate
                                                                        // Column schema map and Child table 
                                                                        // schema map in it
        } 
 
        private bool AddColumnSchema(DataColumn col, XmlNameTable nameTable, XmlNodeIdHashtable columns) {
            string columnLocalName = nameTable.Get(col.EncodedColumnName ); 
            string columnNamespace = nameTable.Get(col.Namespace   );
            if(columnLocalName == null) {
                return false;
            } 
            XmlNodeIdentety idColumn = new XmlNodeIdentety(columnLocalName, columnNamespace);
 
            columns[idColumn] = col; 

            if (col.ColumnName.StartsWith("xml", StringComparison.OrdinalIgnoreCase)) { 
                HandleSpecialColumn(col, nameTable, columns);
            }

 
            return true;
        } 
 
        private bool AddColumnSchema(XmlNameTable nameTable, DataColumn col, XmlNodeIdHashtable columns) {
            string _columnLocalName = XmlConvert.EncodeLocalName(col.ColumnName); 
            string columnLocalName = nameTable.Get(_columnLocalName);           // Look it up in a name table

            if(columnLocalName == null) {                                       // Not found?
                columnLocalName = nameTable.Add(_columnLocalName);              // Add it 
            }
 
            col.encodedColumnName = columnLocalName;                            // And set it back 

            string columnNamespace = nameTable.Get(col.Namespace );             // Get column namespace from nametable 

            if(columnNamespace == null) {                                       // Not found ?
                columnNamespace = nameTable.Add(col.Namespace);                 // Add it
            } 
            else {
                if (col._columnUri != null )                                    // Update namespace 
                    col._columnUri = columnNamespace; 
            }
                                                                                // Create XmlNodeIdentety 
                                                                                // for this column
            XmlNodeIdentety idColumn = new XmlNodeIdentety(columnLocalName, columnNamespace);
            columns[idColumn] = col;                                            // And add it to hashtable
 
            if (col.ColumnName.StartsWith("xml", StringComparison.OrdinalIgnoreCase)) {
                HandleSpecialColumn(col, nameTable, columns); 
            } 

            return true; 
        }

        private void BuildIdentityMap(DataSet dataSet, XmlNameTable nameTable) {
 
            this.tableSchemaMap    = new XmlNodeIdHashtable(dataSet.Tables.Count);
 
            foreach(DataTable t in dataSet.Tables) { 
                TableSchemaInfo tableSchemaInfo = AddTableSchema(t, nameTable);
                if(tableSchemaInfo != null) { 
                    foreach( DataColumn c in t.Columns ) {
                        // don't include auto-generated PK, FK and any hidden columns to be part of mapping
                        if (IsMappedColumn(c)) {
                            AddColumnSchema(c, nameTable, tableSchemaInfo.ColumnsSchemaMap); 
                        }
                    } 
                } 
            }
        } 

        // This one is used while reading data with preloaded schema

        private void BuildIdentityMap(XmlNameTable nameTable, DataSet dataSet) { 
            this.tableSchemaMap    = new XmlNodeIdHashtable(dataSet.Tables.Count);
                                                                        // This hash table contains 
                                                                        // tables schemas as TableSchemaInfo objects 
                                                                        // These objects holds reference to the table.
                                                                        // Hash tables with columns schema maps 
                                                                        // and child tables schema maps

            string dsNamespace = nameTable.Get(dataSet.Namespace);      // Attept to look up DataSet namespace
                                                                        // in the name table 

            if (dsNamespace == null) {                                  // Found ? 
                dsNamespace = nameTable.Add(dataSet.Namespace);         // Nope. Add it 
            }
            dataSet.namespaceURI = dsNamespace;                         // Set a DataSet namespace URI 


            foreach(DataTable t in dataSet.Tables) {                    // For each table
 
                TableSchemaInfo tableSchemaInfo = AddTableSchema(nameTable, t);
                                                                        // Add table schema info to hash table 
 
                if(tableSchemaInfo != null) {
                    foreach( DataColumn c in t.Columns ) {              // Add column schema map 
                        // don't include auto-generated PK, FK and any hidden columns to be part of mapping
                        if (IsMappedColumn(c)) {                        // If mapped column
                            AddColumnSchema(nameTable, c, tableSchemaInfo.ColumnsSchemaMap);
                        }                                               // Add it to the map 
                    }
 
                    // Add child nested tables to the schema 

                    foreach( DataRelation r in t.ChildRelations ) {     // Do we have a child tables ? 
                        if (r.Nested) {                                 // Is it nested?
                            // don't include non nested tables

                            // Handle namespaces and names as usuall 

                            string _tableLocalName = XmlConvert.EncodeLocalName(r.ChildTable.TableName); 
                            string tableLocalName = nameTable.Get(_tableLocalName); 

                            if(tableLocalName == null) { 
                                tableLocalName = nameTable.Add(_tableLocalName);
                            }

                            string tableNamespace = nameTable.Get(r.ChildTable.Namespace ); 

                            if(tableNamespace == null) { 
                                tableNamespace = nameTable.Add(r.ChildTable.Namespace); 
                            }
 
                            XmlNodeIdentety idTable = new XmlNodeIdentety(tableLocalName, tableNamespace);
                            tableSchemaInfo.ColumnsSchemaMap[idTable] = r.ChildTable;

                        } 
                    }
                } 
            } 
        }
 
        // Used for inference

        private void BuildIdentityMap(DataTable dataTable, XmlNameTable nameTable) {
            this.tableSchemaMap    = new XmlNodeIdHashtable(1); 

            TableSchemaInfo tableSchemaInfo = AddTableSchema(dataTable, nameTable); 
            if(tableSchemaInfo != null) { 
                foreach( DataColumn c in dataTable.Columns ) {
                      // don't include auto-generated PK, FK and any hidden columns to be part of mapping 
                      if (IsMappedColumn(c)) {
                          AddColumnSchema(c, nameTable, tableSchemaInfo.ColumnsSchemaMap);
                      }
                  } 
            }
 
        } 

        // This one is used while reading data with preloaded schema 

        private void BuildIdentityMap(XmlNameTable nameTable, DataTable dataTable) {

            ArrayList tableList = GetSelfAndDescendants(dataTable);     // Get list of tables we're loading 
                                                                        // This includes our table and
                                                                        // related tables tree 
 
            this.tableSchemaMap = new XmlNodeIdHashtable( tableList.Count );
                                                                        // Create hash table to hold all 
                                                                        // tables to load.

            foreach (DataTable t in tableList) {                        // For each table
 
                TableSchemaInfo tableSchemaInfo = AddTableSchema(nameTable, t );
                                                                        // Create schema info 
                if(tableSchemaInfo != null) { 
                    foreach( DataColumn c in t.Columns ) {              // Add column information
                        // don't include auto-generated PK, FK and any hidden columns to be part of mapping 
                        if (IsMappedColumn(c)) {
                            AddColumnSchema(nameTable, c, tableSchemaInfo.ColumnsSchemaMap);
                        }
                    } 

                    foreach( DataRelation r in t.ChildRelations ) {     // Add nested tables information 
                        if (r.Nested) {                                 // Is it nested? 
                            // don't include non nested tables
 
                            // Handle namespaces and names as usuall

                            string _tableLocalName = XmlConvert.EncodeLocalName(r.ChildTable.TableName);
                            string tableLocalName = nameTable.Get(_tableLocalName); 

                            if(tableLocalName == null) { 
                                tableLocalName = nameTable.Add(_tableLocalName); 
                            }
 
                            string tableNamespace = nameTable.Get(r.ChildTable.Namespace );

                            if(tableNamespace == null) {
                                tableNamespace = nameTable.Add(r.ChildTable.Namespace); 
                            }
 
                            XmlNodeIdentety idTable = new XmlNodeIdentety(tableLocalName, tableNamespace); 
                            tableSchemaInfo.ColumnsSchemaMap[idTable] = r.ChildTable;
 
                        }
                    }
                }
            } 
        }
 
        private ArrayList GetSelfAndDescendants(DataTable dt) { // breadth-first 
             ArrayList tableList = new ArrayList();
             tableList.Add(dt); 
             int nCounter = 0;

             while (nCounter < tableList.Count) {
                foreach(DataRelation childRelations in ((DataTable)tableList[nCounter]).ChildRelations) { 
                    if (!tableList.Contains(childRelations.ChildTable))
                        tableList.Add(childRelations.ChildTable); 
                } 
                nCounter++;
             } 

            return tableList;
        }
        // Used to infer schema and top most node 

        public object GetColumnSchema(XmlNode node, bool fIgnoreNamespace) { 
            Debug.Assert(node != null, "Argument validation"); 
            TableSchemaInfo tableSchemaInfo = null;
 
            XmlNode nodeRegion = (node.NodeType == XmlNodeType.Attribute) ? ((XmlAttribute)node).OwnerElement : node.ParentNode;

            do {
                if(nodeRegion == null || nodeRegion.NodeType != XmlNodeType.Element) { 
                    return null;
                } 
                tableSchemaInfo = (TableSchemaInfo) (fIgnoreNamespace ? tableSchemaMap[nodeRegion.LocalName] : tableSchemaMap[nodeRegion]); 

                nodeRegion = nodeRegion.ParentNode; 
            } while(tableSchemaInfo == null);

            if (fIgnoreNamespace)
                return tableSchemaInfo.ColumnsSchemaMap[node.LocalName]; 
            else
                return tableSchemaInfo.ColumnsSchemaMap[node]; 
 
        }
 

        public object GetColumnSchema(DataTable table, XmlReader dataReader, bool fIgnoreNamespace){
            if ((lastTableSchemaInfo == null) || (lastTableSchemaInfo.TableSchema != table)) {
                lastTableSchemaInfo = (TableSchemaInfo)(fIgnoreNamespace ? tableSchemaMap[table.EncodedTableName] : tableSchemaMap[table]); 
            }
 
            if (fIgnoreNamespace) 
                return lastTableSchemaInfo.ColumnsSchemaMap[dataReader.LocalName];
            return lastTableSchemaInfo.ColumnsSchemaMap[dataReader]; 
        }

        // Used to infer schema
 
        public object GetSchemaForNode(XmlNode node, bool fIgnoreNamespace) {
            TableSchemaInfo tableSchemaInfo = null; 
 
            if (node.NodeType == XmlNodeType.Element) {         // If element
                tableSchemaInfo = (TableSchemaInfo) (fIgnoreNamespace ? tableSchemaMap[node.LocalName] : tableSchemaMap[node]); 
            }                                                   // Look up table schema info for it

            if (tableSchemaInfo != null) {                      // Got info ?
                return tableSchemaInfo.TableSchema;             // Yes, Return table 
            }
 
            return GetColumnSchema(node, fIgnoreNamespace);     // Attempt to locate column 
        }
 
        public DataTable GetTableForNode(XmlReader node, bool fIgnoreNamespace) {
            TableSchemaInfo tableSchemaInfo = (TableSchemaInfo) (fIgnoreNamespace ? tableSchemaMap[node.LocalName] : tableSchemaMap[node]);
            if (tableSchemaInfo != null) {
                lastTableSchemaInfo = tableSchemaInfo; 
                return lastTableSchemaInfo.TableSchema;
            } 
            return null; 
        }
 
        private void HandleSpecialColumn(DataColumn col, XmlNameTable nameTable, XmlNodeIdHashtable columns) {
            // if column name starts with xml, we encode it manualy and add it for look up
            Debug.Assert(col.ColumnName.StartsWith("xml", StringComparison.OrdinalIgnoreCase), "column name should start with xml");
            string tempColumnName; 

            if ('x' == col.ColumnName[0]) { 
                tempColumnName = "_x0078_"; // lower case xml... -> _x0078_ml... 
            }
            else { 
                tempColumnName = "_x0058_"; // upper case Xml... -> _x0058_ml...
            }

            tempColumnName += col.ColumnName.Substring(1); 

            if(nameTable.Get(tempColumnName) == null) { 
                nameTable.Add(tempColumnName); 
            }
            string columnNamespace = nameTable.Get(col.Namespace); 
            XmlNodeIdentety idColumn = new XmlNodeIdentety(tempColumnName, columnNamespace);
            columns[idColumn] = col;
        }
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK