XMLDiffLoader.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 / XMLDiffLoader.cs / 1305376 / XMLDiffLoader.cs

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

namespace System.Data { 
    using System;
    using System.Runtime.Serialization.Formatters;
    using System.Configuration.Assemblies;
    using System.Runtime.InteropServices; 
    using System.Diagnostics;
    using System.IO; 
    using System.Collections; 
    using System.Globalization;
    using Microsoft.Win32; 
    using System.ComponentModel;
    using System.Xml;
    using System.Xml.Serialization;
 
    internal sealed class XMLDiffLoader {
        ArrayList tables; 
        DataSet dataSet = null; 
        DataTable dataTable = null;
 
        internal void LoadDiffGram(DataSet ds, XmlReader dataTextReader) {
            XmlReader reader = DataTextReader.CreateReader(dataTextReader);
            dataSet = ds;
            while (reader.LocalName == Keywords.SQL_BEFORE && reader.NamespaceURI==Keywords.DFFNS)  { 
                ProcessDiffs(ds, reader);
                reader.Read(); // now the reader points to the error section 
            } 

            while (reader.LocalName == Keywords.MSD_ERRORS && reader.NamespaceURI==Keywords.DFFNS) { 
                ProcessErrors(ds, reader);
                Debug.Assert(reader.LocalName == Keywords.MSD_ERRORS && reader.NamespaceURI==Keywords.DFFNS, "something fishy");
                reader.Read(); // pass the end of errors tag
            } 
        }
 
 
        private void CreateTablesHierarchy(DataTable dt) {
            foreach( DataRelation r in dt.ChildRelations ) { 
                if (! tables.Contains((DataTable)r.ChildTable)) {
                    tables.Add((DataTable)r.ChildTable);
                    CreateTablesHierarchy(r.ChildTable)     ;
                } 
            }
        } 
 
        internal void LoadDiffGram(DataTable dt, XmlReader dataTextReader) {
            XmlReader reader = DataTextReader.CreateReader(dataTextReader); 
            dataTable = dt;
            tables = new ArrayList();
            tables.Add(dt);
            CreateTablesHierarchy(dt); 

            while (reader.LocalName == Keywords.SQL_BEFORE && reader.NamespaceURI==Keywords.DFFNS)  { 
                ProcessDiffs(tables, reader); 
                reader.Read(); // now the reader points to the error section
            } 

            while (reader.LocalName == Keywords.MSD_ERRORS && reader.NamespaceURI==Keywords.DFFNS) {
                ProcessErrors(tables, reader);
                Debug.Assert(reader.LocalName == Keywords.MSD_ERRORS && reader.NamespaceURI==Keywords.DFFNS, "something fishy"); 
                reader.Read(); // pass the end of errors tag
            } 
 
        }
 
        internal void ProcessDiffs(DataSet ds, XmlReader ssync) {
            DataTable tableBefore;
            DataRow row;
            int oldRowRecord; 
            int pos = -1;
 
            int iSsyncDepth = ssync.Depth; 
            ssync.Read(); // pass the before node.
 
            SkipWhitespaces(ssync);

            while (iSsyncDepth < ssync.Depth) {
                tableBefore = null; 
                string diffId = null;
 
                oldRowRecord = -1; 

                // the diffgramm always contains sql:before and sql:after pairs 

                int iTempDepth = ssync.Depth;

                diffId = ssync.GetAttribute(Keywords.DIFFID, Keywords.DFFNS); 
                bool hasErrors = (bool) (ssync.GetAttribute(Keywords.HASERRORS, Keywords.DFFNS) == Keywords.TRUE);
                oldRowRecord = ReadOldRowData(ds, ref tableBefore, ref pos, ssync); 
                if (oldRowRecord == -1) 
                    continue;
 
                if (tableBefore == null)
                    throw ExceptionBuilder.DiffgramMissingSQL();

                row = (DataRow)tableBefore.RowDiffId[diffId]; 
                if (row != null) {
                    row.oldRecord = oldRowRecord ; 
                    tableBefore.recordManager[oldRowRecord] = row; 
                } else {
                    row = tableBefore.NewEmptyRow(); 
                    tableBefore.recordManager[oldRowRecord] = row;
                    row.oldRecord = oldRowRecord;
                    row.newRecord = oldRowRecord;
                    tableBefore.Rows.DiffInsertAt(row, pos); 
                    row.Delete();
                    if (hasErrors) 
                        tableBefore.RowDiffId[diffId] = row; 
                }
            } 

            return;
        }
        internal void ProcessDiffs(ArrayList tableList, XmlReader ssync) { 
            DataTable tableBefore;
            DataRow row; 
            int oldRowRecord; 
            int pos = -1;
 
            int iSsyncDepth = ssync.Depth;
            ssync.Read(); // pass the before node.

            //SkipWhitespaces(ssync); for given scenario does not require this change, but in fact we should do it. 

            while (iSsyncDepth < ssync.Depth) { 
                tableBefore = null; 
                string diffId = null;
 
                oldRowRecord = -1;

                // the diffgramm always contains sql:before and sql:after pairs
 
                int iTempDepth = ssync.Depth;
 
                diffId = ssync.GetAttribute(Keywords.DIFFID, Keywords.DFFNS); 
                bool hasErrors = (bool) (ssync.GetAttribute(Keywords.HASERRORS, Keywords.DFFNS) == Keywords.TRUE);
                oldRowRecord = ReadOldRowData(dataSet, ref tableBefore, ref pos, ssync); 
                if (oldRowRecord == -1)
                    continue;

                if (tableBefore == null) 
                    throw ExceptionBuilder.DiffgramMissingSQL();
 
                row = (DataRow)tableBefore.RowDiffId[diffId]; 

                if (row != null) { 
                    row.oldRecord = oldRowRecord ;
                    tableBefore.recordManager[oldRowRecord] = row;
                } else {
                    row = tableBefore.NewEmptyRow(); 
                    tableBefore.recordManager[oldRowRecord] = row;
                    row.oldRecord = oldRowRecord; 
                    row.newRecord = oldRowRecord; 
                    tableBefore.Rows.DiffInsertAt(row, pos);
                    row.Delete(); 
                    if (hasErrors)
                        tableBefore.RowDiffId[diffId] = row;
                }
            } 

            return; 
 
        }
 

        internal void ProcessErrors(DataSet ds, XmlReader ssync) {
            DataTable table;
 
            int iSsyncDepth = ssync.Depth;
            ssync.Read(); // pass the before node. 
 
            while (iSsyncDepth < ssync.Depth) {
                table = ds.Tables.GetTable(XmlConvert.DecodeName(ssync.LocalName), ssync.NamespaceURI); 
                if (table == null)
                    throw ExceptionBuilder.DiffgramMissingSQL();
                string diffId = ssync.GetAttribute(Keywords.DIFFID, Keywords.DFFNS);
                DataRow row = (DataRow)table.RowDiffId[diffId]; 
                string rowError = ssync.GetAttribute(Keywords.MSD_ERROR, Keywords.DFFNS);
                if (rowError != null) 
                    row.RowError = rowError; 
                int iRowDepth = ssync.Depth;
                ssync.Read(); // we may be inside a column 
                while (iRowDepth < ssync.Depth) {
                    if (XmlNodeType.Element == ssync.NodeType) {
                        DataColumn col = table.Columns[XmlConvert.DecodeName(ssync.LocalName), ssync.NamespaceURI];
                        //if (col == null) 
                        // throw exception here
                        string colError = ssync.GetAttribute(Keywords.MSD_ERROR, Keywords.DFFNS); 
                        row.SetColumnError(col, colError); 
                    }
 
                    ssync.Read();
                }
                while ((ssync.NodeType == XmlNodeType.EndElement) && (iSsyncDepth < ssync.Depth) )
                    ssync.Read(); 

            } 
 
            return;
        } 

        internal void ProcessErrors(ArrayList dt, XmlReader ssync) {
            DataTable table;
 
            int iSsyncDepth = ssync.Depth;
            ssync.Read(); // pass the before node. 
 
            while (iSsyncDepth < ssync.Depth) {
                table = GetTable(XmlConvert.DecodeName(ssync.LocalName), ssync.NamespaceURI); 
                if (table == null)
                    throw ExceptionBuilder.DiffgramMissingSQL();

                string diffId = ssync.GetAttribute(Keywords.DIFFID, Keywords.DFFNS); 

                DataRow row = (DataRow)table.RowDiffId[diffId]; 
                if (row  == null) { 
                    for(int i = 0; i < dt.Count; i++) {
                        row = (DataRow)((DataTable)dt[i]).RowDiffId[diffId]; 
                        if (row != null) {
                            table = row.Table;
                            break;
                        } 
                    }
                } 
                string rowError = ssync.GetAttribute(Keywords.MSD_ERROR, Keywords.DFFNS); 
                if (rowError != null)
                    row.RowError = rowError; 
                int iRowDepth = ssync.Depth;
                ssync.Read(); // we may be inside a column

                while (iRowDepth < ssync.Depth) { 
                    if (XmlNodeType.Element == ssync.NodeType) {
                        DataColumn col = table.Columns[XmlConvert.DecodeName(ssync.LocalName), ssync.NamespaceURI]; 
                        //if (col == null) 
                        // throw exception here
                        string colError = ssync.GetAttribute(Keywords.MSD_ERROR, Keywords.DFFNS); 
                        row.SetColumnError(col, colError);
                    }
                    ssync.Read();
                } 
                while ((ssync.NodeType == XmlNodeType.EndElement) && (iSsyncDepth < ssync.Depth) )
                    ssync.Read(); 
 
            }
 
            return;
        }
        private DataTable GetTable(string tableName, string ns) {
            if (tables == null) 
                return dataSet.Tables.GetTable(tableName, ns);
 
            if (tables.Count == 0) 
                return (DataTable)tables[0];
 
            for(int i = 0; i < tables.Count; i++) {
                DataTable dt = (DataTable)tables[i];
                if ((string.Compare(dt.TableName, tableName, StringComparison.Ordinal) == 0)
                    && (string.Compare(dt.Namespace, ns, StringComparison.Ordinal) == 0)) 
                    return dt;
            } 
            return null; 
        }
 
        private int ReadOldRowData(DataSet ds, ref DataTable table, ref int pos, XmlReader row) {
            // read table information
            if (ds != null) {
                table = ds.Tables.GetTable(XmlConvert.DecodeName(row.LocalName), row.NamespaceURI); 
            }
            else { 
                table = GetTable(XmlConvert.DecodeName(row.LocalName), row.NamespaceURI); 
            }
 
            if (table == null) {
                row.Skip(); // need to skip this element if we dont know about it, before returning -1
                return -1;
            } 

            int iRowDepth = row.Depth; 
            string value = null; 

            if (table == null) 
                throw ExceptionBuilder.DiffgramMissingTable(XmlConvert.DecodeName(row.LocalName));


            value = row.GetAttribute(Keywords.ROWORDER, Keywords.MSDNS); 
            if (!Common.ADP.IsEmpty(value)) {
                pos = (Int32) Convert.ChangeType(value, typeof(Int32), null); 
            } 

            int record = table.NewRecord(); 
            foreach (DataColumn col in table.Columns) {
                col[record] = DBNull.Value;
            }
 
            foreach (DataColumn col in table.Columns) {
                if ((col.ColumnMapping == MappingType.Element) || 
                    (col.ColumnMapping == MappingType.SimpleContent)) 
                    continue;
 
                if (col.ColumnMapping == MappingType.Hidden) {
                    value = row.GetAttribute("hidden"+col.EncodedColumnName, Keywords.MSDNS);
                }
                else { 
                    value = row.GetAttribute(col.EncodedColumnName, col.Namespace);
                } 
 
                if (value == null) {
                    continue; 
                }

                col[record] = col.ConvertXmlToObject(value);
            } 

            row.Read(); 
            SkipWhitespaces(row); 

            if (row.Depth <= iRowDepth) { 
                // the node is empty
                return record;
            }
 
            if (table.XmlText != null) {
                DataColumn col = table.XmlText; 
                col[record] = col.ConvertXmlToObject(row.ReadString()); 
            }
            else { 
                while (row.Depth > iRowDepth)  {
                    String ln =XmlConvert.DecodeName( row.LocalName) ;
                    String ns = row.NamespaceURI;
                    DataColumn column = table.Columns[ln, ns]; 

                    if (column == null) { 
                        while((row.NodeType != XmlNodeType.EndElement) && (row.LocalName!=ln) && (row.NamespaceURI!=ns)) 
                            row.Read(); // consume the current node
                        row.Read(); // now points to the next column 
                        //SkipWhitespaces(row); seems no need, just in case if we see other issue , this will be here as hint
                        continue;// add a read here!
                    }
 
                    if (column.IsCustomType) {
                        // if column's type is object or column type does not implement IXmlSerializable 
                        bool isPolymorphism = (column.DataType == typeof(Object)|| (row.GetAttribute(Keywords.MSD_INSTANCETYPE, Keywords.MSDNS) != null) || 
                        (row.GetAttribute(Keywords.TYPE, Keywords.XSINS) != null)) ;
 
                        bool skipped = false;
                        if (column.Table.DataSet != null && column.Table.DataSet.UdtIsWrapped) {
                            row.Read(); // if UDT is wrapped, skip the wrapper
                            skipped = true; 
                        }
 
                        XmlRootAttribute xmlAttrib = null; 

                        if (!isPolymorphism && !column.ImplementsIXMLSerializable) { // THIS 
                            // if does not implement IXLSerializable, need to go with XmlSerializer: pass XmlRootAttribute
                            if (skipped) {
                                xmlAttrib = new XmlRootAttribute(row.LocalName);
                                xmlAttrib.Namespace = row.NamespaceURI ; 
                            }
                            else { 
                                xmlAttrib = new XmlRootAttribute(column.EncodedColumnName); 
                                xmlAttrib.Namespace = column.Namespace;
                            } 
                        }
                        // for else case xmlAttrib MUST be null
                        column[record] = column.ConvertXmlToObject(row, xmlAttrib); // you need to pass null XmlAttib here
 

                        if (skipped) { 
                            row.Read(); // if Wrapper is skipped, skip its end tag 
                        }
                    } 
                    else {
                        int iColumnDepth = row.Depth;
                        row.Read();
 
                        // SkipWhitespaces(row);seems no need, just in case if we see other issue , this will be here as hint
                        if (row.Depth > iColumnDepth) { //we are inside the column 
                            if (row.NodeType == XmlNodeType.Text || row.NodeType == XmlNodeType.Whitespace || row.NodeType == XmlNodeType.SignificantWhitespace) { 
                                String text = row.ReadString();
                                column[record] = column.ConvertXmlToObject(text); 

                                row.Read(); // now points to the next column
                            }
                        } 
                        else {
                            //  case 
                            if (column.DataType == typeof(string)) 
                                column[record] = string.Empty;
                        } 
                    }
                }
            }
            row.Read(); //now it should point to next row 
            SkipWhitespaces(row);
            return record; 
        } 

        internal void SkipWhitespaces(XmlReader reader) { 
            while (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.SignificantWhitespace) {
                reader.Read();
            }
        } 
    }
} 

// 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