2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Data / System.Data / DataSet.cs
index 8b9b54fbf7d5e0a129adc98d8b13a2ba50447875..17815bb815c8470fbe16b9a96b5177be529e6eb6 100644 (file)
@@ -8,9 +8,33 @@
 //   Stuart Caborn <stuart.caborn@virgin.net>
 //   Tim Coleman (tim@timcoleman.com)
 //   Ville Palo <vi64pa@koti.soon.fi>
+//   Atsushi Enomoto <atsushi@ximian.com>
 //
 // (C) Ximian, Inc. 2002
-// Copyright (C) Tim Coleman, 2002
+// Copyright (C) Tim Coleman, 2002, 2003
+//
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
 using System;
@@ -22,17 +46,19 @@ using System.IO;
 using System.Runtime.Serialization;
 using System.Xml;
 using System.Xml.Schema;
+using System.Xml.Serialization;
+using System.Data.Common;
 
 namespace System.Data {
-       /// <summary>
-       /// an in-memory cache of data 
-       /// </summary>
-       //[Designer]
+
        [ToolboxItem (false)]
        [DefaultProperty ("DataSetName")]
+       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataSetDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
+
        [Serializable]
-       public class DataSet : MarshalByValueComponent, IListSource,
-               ISupportInitialize, ISerializable {
+       public class DataSet : MarshalByValueComponent, IListSource, 
+               ISupportInitialize, ISerializable, IXmlSerializable 
+       {
                private string dataSetName;
                private string _namespace = "";
                private string prefix;
@@ -42,23 +68,29 @@ namespace System.Data {
                private DataRelationCollection relationCollection;
                private PropertyCollection properties;
                private DataViewManager defaultView;
-               private CultureInfo locale;
+               private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
+               internal XmlDataDocument _xmlDataDocument = null;
                
                #region Constructors
 
-               public DataSet() : this ("NewDataSet") {                
+               public DataSet () : this ("NewDataSet") 
+               {               
                }
-
-               public DataSet(string name) {
+               
+               public DataSet (string name)
+               {
                        dataSetName = name;
                        tableCollection = new DataTableCollection (this);
                        relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
-                       properties = new PropertyCollection();
+                       properties = new PropertyCollection ();
+                       this.prefix = String.Empty;
+                       
+                       this.Locale = CultureInfo.CurrentCulture;
                }
 
-               [MonoTODO]
-               protected DataSet(SerializationInfo info, StreamingContext context) : this () {
-                       throw new NotImplementedException ();
+               protected DataSet (SerializationInfo info, StreamingContext context) : this ()
+               {
+                       GetSerializationData (info, context);
                }
 
                #endregion // Constructors
@@ -69,14 +101,17 @@ namespace System.Data {
                [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
                [DefaultValue (false)]
                public bool CaseSensitive {
-                       get { return caseSensitive; } 
+                       get {
+                               return caseSensitive;
+                       } 
                        set {
-                               foreach (DataTable T in Tables) {
-                                       if (T.VirginCaseSensitive)
-                                               T.CaseSensitive = value;
-                               }
-
                                caseSensitive = value; 
+                               if (!caseSensitive) {
+                                       foreach (DataTable table in Tables) {
+                                               foreach (Constraint c in table.Constraints)
+                                                       c.AssertConstraint ();
+                                       }
+                               }
                        }
                }
 
@@ -102,7 +137,21 @@ namespace System.Data {
                [DefaultValue (true)]
                public bool EnforceConstraints {
                        get { return enforceConstraints; } 
-                       set { enforceConstraints = value; }
+                       set { 
+                               if (value != enforceConstraints) {
+                                       enforceConstraints = value; 
+                                       if (value) {
+                                               foreach (DataTable table in Tables) {
+                                                       // first assert all unique constraints
+                                                       foreach (UniqueConstraint uc in table.Constraints.UniqueConstraints)
+                                                               uc.AssertConstraint ();
+                                                       // then assert all foreign keys
+                                                       foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
+                                                               fk.AssertConstraint ();
+                                               }
+                                       }
+                               }
+                       }
                }
 
                [Browsable (false)]
@@ -117,7 +166,11 @@ namespace System.Data {
                public bool HasErrors {
                        [MonoTODO]
                        get {
-                               throw new NotImplementedException ();
+                               for (int i = 0; i < Tables.Count; i++) {
+                                       if (Tables[i].HasErrors)
+                                               return true;
+                               }
+                               return false;
                        }
                }
 
@@ -128,7 +181,7 @@ namespace System.Data {
                                return locale;
                        }
                        set {
-                               if (locale == null || !locale.Equals(value)) {
+                               if (locale == null || !locale.Equals (value)) {
                                        // TODO: check if the new locale is valid
                                        // TODO: update locale of all tables
                                        locale = value;
@@ -151,7 +204,6 @@ namespace System.Data {
                        Merge (table, false, MissingSchemaAction.Add);
                }
                
-               [MonoTODO]
                public void Merge (DataSet dataSet, bool preserveChanges)
                {
                        Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
@@ -160,31 +212,56 @@ namespace System.Data {
                [MonoTODO]
                public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
                {
-                       throw new NotImplementedException();
+                       if (rows == null)
+                               throw new ArgumentNullException ("rows");
+                       if (!IsLegalSchemaAction (missingSchemaAction))
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
+                       
+                       MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
                }
                
                [MonoTODO]
                public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
                {
-                       throw new NotImplementedException();
+                       if (dataSet == null)
+                               throw new ArgumentNullException ("dataSet");
+                       if (!IsLegalSchemaAction (missingSchemaAction))
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
+                       
+                       MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
                }
                
                [MonoTODO]
                public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
                {
-                       throw new NotImplementedException();
+                       if (table == null)
+                               throw new ArgumentNullException ("table");
+                       if (!IsLegalSchemaAction (missingSchemaAction))
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
+                       
+                       MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
+               }
+
+               private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
+               {
+                       if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
+                               || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
+                               return true;
+                       return false;
                }
                
                [DataCategory ("Data")]
                [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
                [DefaultValue ("")]
                public string Namespace {
-                       [MonoTODO]
                        get { return _namespace; } 
-                       [MonoTODO]
                        set {
                                //TODO - trigger an event if this happens?
-                               _namespace = value;
+                               if (value == null)
+                                       value = String.Empty;
+                                if (value != this._namespace)
+                                        RaisePropertyChanging ("Namespace");
+                               _namespace = value;
                        }
                }
 
@@ -192,11 +269,22 @@ namespace System.Data {
                [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
                [DefaultValue ("")]
                public string Prefix {
-                       [MonoTODO]
                        get { return prefix; } 
-                       [MonoTODO]
                        set {
-                               //TODO - trigger an event if this happens?
+                               if (value == null)
+                                       value = String.Empty;
+                              // Prefix cannot contain any special characters other than '_' and ':'
+                               for (int i = 0; i < value.Length; i++) {
+                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
+                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
+                               }
+
+
+                               if (value == null)
+                                       value = string.Empty;
+                               
+                               if (value != this.prefix) 
+                                       RaisePropertyChanging ("Prefix");
                                prefix = value;
                        }
                }
@@ -236,44 +324,66 @@ namespace System.Data {
                #region Public Methods
 
                [MonoTODO]
-               public void AcceptChanges()
+               public void AcceptChanges ()
                {
                        foreach (DataTable tempTable in tableCollection)
                                tempTable.AcceptChanges ();
                }
 
-               public void Clear()
+                /// <summary>
+                /// Clears all the tables
+                /// </summary>
+               public void Clear ()
                {
-                       throw new NotImplementedException ();
+                       if (_xmlDataDocument != null)
+                               throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet.");
+                        bool enforceConstraints = this.EnforceConstraints;
+                        this.EnforceConstraints = false;
+                        for (int t = 0; t < tableCollection.Count; t++) {
+                               tableCollection[t].Clear ();
+                       }
+                        this.EnforceConstraints = enforceConstraints;
                }
 
-               public virtual DataSet Clone()
+               public virtual DataSet Clone ()
                {
-                       DataSet Copy = new DataSet ();
+                       // need to return the same type as this...
+                       DataSet Copy = (DataSet) Activator.CreateInstance(GetType(), true);
+       
                        CopyProperties (Copy);
 
                        foreach (DataTable Table in Tables) {
-                               Copy.Tables.Add (Table.Clone ());
-                       }       
+                       // tables are often added in no-args constructor, don't add them
+                       // twice.
+                               if (!Copy.Tables.Contains(Table.TableName)) {
+                                       Copy.Tables.Add (Table.Clone ());
+                               }
+                       }
+
+                       //Copy Relationships between tables after existance of tables
+                       //and setting properties correctly
+                       CopyRelations (Copy);
                        
                        return Copy;
                }
 
                // Copies both the structure and data for this DataSet.
-               public DataSet Copy()
+               public DataSet Copy ()
                {
                        DataSet Copy = new DataSet ();
                        CopyProperties (Copy);
 
                        // Copy DatSet's tables
-                       foreach (DataTable Table in Tables) {                           
+                       foreach (DataTable Table in Tables) 
                                Copy.Tables.Add (Table.Copy ());
-                       }
+
+                       //Copy Relationships between tables after existance of tables
+                       //and setting properties correctly
+                       CopyRelations (Copy);
 
                        return Copy;
                }
 
-               [MonoTODO]
                private void CopyProperties (DataSet Copy)
                {
                        Copy.CaseSensitive = CaseSensitive;
@@ -282,35 +392,138 @@ namespace System.Data {
                        //Copy.DefaultViewManager
                        //Copy.DesignMode
                        Copy.EnforceConstraints = EnforceConstraints;
-                       //Copy.ExtendedProperties 
-                       //Copy.HasErrors
-                       //Copy.Locale = Locale;
+                       if(ExtendedProperties.Count > 0) {
+                               //  Cannot copy extended properties directly as the property does not have a set accessor
+                Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
+                ExtendedProperties.Keys.CopyTo (tgtArray, 0);
+                for (int i=0; i < ExtendedProperties.Count; i++)
+                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
+                       }
+            Copy.Locale = Locale;
                        Copy.Namespace = Namespace;
-                       Copy.Prefix = Prefix;
-                       //Copy.Relations = Relations;
-                       //Copy.Site = Site;
+                       Copy.Prefix = Prefix;                   
+                       //Copy.Site = Site; // FIXME : Not sure of this.
+
+               }
+               
+               
+               private void CopyRelations (DataSet Copy)
+               {
 
+                       //Creation of the relation contains some of the properties, and the constructor
+                       //demands these values. instead changing the DataRelation constructor and behaviour the
+                       //parameters are pre-configured and sent to the most general constructor
+
+                       foreach (DataRelation MyRelation in this.Relations) {
+                               string pTable = MyRelation.ParentTable.TableName;
+                               string cTable = MyRelation.ChildTable.TableName;
+                               DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length]; 
+                               DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
+                               int i = 0;
+                               
+                               foreach (DataColumn DC in MyRelation.ParentColumns) {
+                                       P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
+                                       i++;
+                               }
+
+                               i = 0;
+
+                               foreach (DataColumn DC in MyRelation.ChildColumns) {
+                                       C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
+                                       i++;
+                               }
+                               
+                               DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
+                               //cRel.ChildColumns = MyRelation.ChildColumns;
+                               //cRel.ChildTable = MyRelation.ChildTable;
+                               //cRel.ExtendedProperties = cRel.ExtendedProperties; 
+                               //cRel.Nested = MyRelation.Nested;
+                               //cRel.ParentColumns = MyRelation.ParentColumns;
+                               //cRel.ParentTable = MyRelation.ParentTable;
+                                                               
+                               Copy.Relations.Add (cRel);
+                       }
                }
 
-               public DataSet GetChanges()
+               
+
+
+               public DataSet GetChanges ()
                {
-                       throw new NotImplementedException ();
+                       return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
                }
 
                
-               public DataSet GetChanges(DataRowState rowStates)
+               public DataSet GetChanges (DataRowState rowStates)
+               {
+                       if (!HasChanges (rowStates))
+                               return null;
+                       
+                       DataSet copySet = Clone ();
+                       Hashtable addedRows = new Hashtable ();
+
+                       IEnumerator tableEnumerator = Tables.GetEnumerator ();
+                       DataTable origTable;
+                       DataTable copyTable;
+                       while (tableEnumerator.MoveNext ()) {
+                               origTable = (DataTable)tableEnumerator.Current;
+                               copyTable = copySet.Tables[origTable.TableName];
+                               
+                               // Look for relations that have this table as child
+                               IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
+
+                               IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
+                               while (rowEnumerator.MoveNext ()) {
+                                       DataRow row = (DataRow)rowEnumerator.Current;
+                                       
+                                       if (row.IsRowChanged (rowStates))
+                                               AddChangedRow (addedRows, copySet, copyTable, relations, row);
+                               }
+                       }
+                       return copySet;
+               }
+               
+               void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
+               {
+                       if (addedRows.ContainsKey (row)) return;
+                       
+                       relations.Reset ();
+                       while (relations.MoveNext ()) {
+                               DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
+                               if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
+                               DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
+                               AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
+                       }
+               
+                       DataRow newRow = copyTable.NewRow ();
+                       row.CopyValuesToRow (newRow);
+                       copyTable.Rows.Add (newRow);
+                       newRow.XmlRowID = row.XmlRowID;
+                       addedRows.Add (row,row);
+               }
+
+#if NET_2_0
+               [MonoTODO]
+               public DataTableReader GetDataReader (DataTable[] dataTables)
                {
                        throw new NotImplementedException ();
                }
 
-               public string GetXml()
+               [MonoTODO]
+               public DataTableReader GetDataReader ()
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
+               
+               public string GetXml ()
                {
                        StringWriter Writer = new StringWriter ();
                        WriteXml (Writer, XmlWriteMode.IgnoreSchema);
                        return Writer.ToString ();
                }
 
-               public string GetXmlSchema()
+               public string GetXmlSchema ()
                {
                        StringWriter Writer = new StringWriter ();
                        WriteXmlSchema (Writer);
@@ -318,35 +531,62 @@ namespace System.Data {
                }
 
                [MonoTODO]
-               public bool HasChanges()
+               public bool HasChanges ()
                {
-                       throw new NotImplementedException ();
+                       return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
                }
 
                [MonoTODO]
-               public bool HasChanges(DataRowState rowState)
+               public bool HasChanges (DataRowState rowState)
+               {
+                       if (((int)rowState & 0xffffffe0) != 0)
+                               throw new ArgumentOutOfRangeException ("rowState");
+
+                       DataTableCollection tableCollection = Tables;
+                       DataTable table;
+                       DataRowCollection rowCollection;
+                       DataRow row;
+
+                       for (int i = 0; i < tableCollection.Count; i++) {
+                               table = tableCollection[i];
+                               rowCollection = table.Rows;
+                               for (int j = 0; j < rowCollection.Count; j++) {
+                                       row = rowCollection[j];
+                                       if ((row.RowState & rowState) != 0)
+                                               return true;
+                               }
+                       }
+
+                       return false;           
+               }
+
+               public void InferXmlSchema (XmlReader reader, string[] nsArray)
                {
-                       throw new NotImplementedException ();
+                       if (reader == null)
+                               return;
+                       XmlDocument doc = new XmlDocument ();
+                       doc.Load (reader);
+                       InferXmlSchema (doc, nsArray);
                }
 
-               [MonoTODO]
-               public void InferXmlSchema(XmlReader reader, string[] nsArray)
+               private void InferXmlSchema (XmlDocument doc, string [] nsArray)
                {
+                       XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
                }
 
-               public void InferXmlSchema(Stream stream, string[] nsArray)
+               public void InferXmlSchema (Stream stream, string[] nsArray)
                {
-                       InferXmlSchema (new XmlTextReader(stream), nsArray);
+                       InferXmlSchema (new XmlTextReader (stream), nsArray);
                }
 
-               public void InferXmlSchema(TextReader reader, string[] nsArray)
+               public void InferXmlSchema (TextReader reader, string[] nsArray)
                {
-                       InferXmlSchema (new XmlTextReader(reader), nsArray);
+                       InferXmlSchema (new XmlTextReader (reader), nsArray);
                }
 
-               public void InferXmlSchema(string fileName, string[] nsArray)
+               public void InferXmlSchema (string fileName, string[] nsArray)
                {
-                       XmlTextReader reader = new XmlTextReader(fileName);
+                       XmlTextReader reader = new XmlTextReader (fileName);
                        try {
                                InferXmlSchema (reader, nsArray);
                        } finally {
@@ -354,155 +594,226 @@ namespace System.Data {
                        }
                }
 
-               public virtual void RejectChanges()
+#if NET_2_0
+               [MonoTODO]
+               public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
                {
                        throw new NotImplementedException ();
                }
 
-               public virtual void Reset()
+               [MonoTODO]
+               public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
                {
                        throw new NotImplementedException ();
                }
+#endif
 
-               public void WriteXml(Stream stream)
+               public virtual void RejectChanges ()
                {
-                       XmlWriter writer = new XmlTextWriter(stream, null );
+                       int i;
+                       bool oldEnforceConstraints = this.EnforceConstraints;
+                       this.EnforceConstraints = false;
                        
-                       WriteXml( writer );
+                       for (i = 0; i < this.Tables.Count;i++) 
+                               this.Tables[i].RejectChanges ();
+
+                       this.EnforceConstraints = oldEnforceConstraints;
+               }
+
+               public virtual void Reset ()
+               {
+                       IEnumerator constraintEnumerator;
+
+                       // first we remove all ForeignKeyConstraints (if we will not do that
+                       // we will get an exception when clearing the tables).
+                       for (int i = 0; i < Tables.Count; i++) {
+                               ConstraintCollection cc = Tables[i].Constraints;
+                               for (int j = 0; j < cc.Count; j++) {
+                                       if (cc[j] is ForeignKeyConstraint)
+                                               cc.Remove (cc[j]);
+                               }
+                       }
+
+                       Clear ();
+                       Relations.Clear ();
+                       Tables.Clear ();
+               }
+
+               public void WriteXml (Stream stream)
+               {
+                       XmlTextWriter writer = new XmlTextWriter (stream, null);
+                       writer.Formatting = Formatting.Indented;
+                       WriteXml (writer);
                }
 
                ///<summary>
                /// Writes the current data for the DataSet to the specified file.
                /// </summary>
                /// <param name="filename">Fully qualified filename to write to</param>
-               public void WriteXml(string fileName)
+               public void WriteXml (string fileName)
                {
-                       XmlWriter writer = new XmlTextWriter(fileName, null );
-                       
-                       WriteXml( writer );
+                       XmlTextWriter writer = new XmlTextWriter (fileName, null);
+                       writer.Formatting = Formatting.Indented;
+                       writer.WriteStartDocument (true);
+                       try {
+                               WriteXml (writer);
+                       }
+                       finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
-               public void WriteXml(TextWriter writer)
+               public void WriteXml (TextWriter writer)
                {
-                       XmlWriter xwriter = new XmlTextWriter(writer );
-                       
-                       WriteXml( xwriter );
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);
+                       xwriter.Formatting = Formatting.Indented;
+                       WriteXml (xwriter);
                }
 
-               public void WriteXml(XmlWriter writer)
+               public void WriteXml (XmlWriter writer)
                {
-                       WriteXml( writer, XmlWriteMode.IgnoreSchema );
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
                }
 
-               public void WriteXml(Stream stream, XmlWriteMode mode)
+               public void WriteXml (string filename, XmlWriteMode mode)
                {
-                       XmlWriter writer = new XmlTextWriter(stream, null );
+                       XmlTextWriter writer = new XmlTextWriter (filename, null);
+                       writer.Formatting = Formatting.Indented;
+                       writer.WriteStartDocument (true);
                        
-                       WriteXml( writer, mode );
+                       try {
+                               WriteXml (writer, mode);
+                       }
+                       finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
-               public void WriteXml(string fileName, XmlWriteMode mode)
+               public void WriteXml (Stream stream, XmlWriteMode mode)
                {
-                       XmlWriter writer = new XmlTextWriter(fileName, null );
-                       
-                       WriteXml( writer, mode );
+                       XmlTextWriter writer = new XmlTextWriter (stream, null);
+                       writer.Formatting = Formatting.Indented;
+                       WriteXml (writer, mode);
                }
 
-               public void WriteXml(TextWriter writer, XmlWriteMode mode)
+               public void WriteXml (TextWriter writer, XmlWriteMode mode)
                {
-                       XmlWriter xwriter = new XmlTextWriter(writer);
-                       
-                       WriteXml( xwriter, mode );
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);
+                       xwriter.Formatting = Formatting.Indented;
+                       WriteXml (xwriter, mode);
                }
 
-               public void WriteXml(XmlWriter writer, XmlWriteMode mode)
+               public void WriteXml (XmlWriter writer, XmlWriteMode mode)
                {
-                       ((XmlTextWriter)writer).Formatting = Formatting.Indented;
-                       WriteStartElement( writer, mode, Namespace, Prefix, DataSetName );
-                       
-                       if( mode == XmlWriteMode.WriteSchema )
-                       {
-                               DoWriteXmlSchema( writer );
+                       if (mode == XmlWriteMode.DiffGram) {
+                               SetRowsID();
+                               WriteDiffGramElement(writer);
                        }
                        
-                       //Write out each table in order, providing it is not
-                       //part of another table structure via a nested parent relationship
-                       foreach( DataTable table in Tables )
-                       {
-                               bool isTopLevel = true;
-                               foreach( DataRelation rel in table.ParentRelations )
-                               {
-                                       if( rel.Nested )
-                                       {
-                                               isTopLevel = false;
-                                               break;
-                                       }
-                               }
+                       // It should not write when there is no content to be written
+                       bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
+                       for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)
+                               shouldOutputContent = tableCollection [n].Rows.Count > 0;
+                               
+                       if (shouldOutputContent) {
+                               WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
+                               
+                               if (mode == XmlWriteMode.WriteSchema)
+                                       DoWriteXmlSchema (writer);
                                
-                               if( isTopLevel )
-                               {
-                                       WriteTable(  writer, table, mode );
+                               WriteTables (writer, mode, Tables, DataRowVersion.Default);
+                               writer.WriteEndElement ();
+                       }
+                       
+                       if (mode == XmlWriteMode.DiffGram) {
+                               if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
+
+                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
+                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
+                                       WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
+                                       writer.WriteEndElement ();
                                }
                        }
                        
-                       writer.WriteEndElement();                       
+                       if (mode == XmlWriteMode.DiffGram)
+                               writer.WriteEndElement (); // diffgr:diffgram
+
+                       writer.Flush ();
                }
 
-               public void WriteXmlSchema(Stream stream)
+               public void WriteXmlSchema (Stream stream)
                {
-                       XmlWriter writer = new XmlTextWriter(stream, null  );
-                       
-                       WriteXmlSchema( writer );       
+                       XmlTextWriter writer = new XmlTextWriter (stream, null );
+                       writer.Formatting = Formatting.Indented;
+                       WriteXmlSchema (writer);        
                }
 
-               public void WriteXmlSchema(string fileName)
+               public void WriteXmlSchema (string fileName)
                {
-                       XmlWriter writer = new XmlTextWriter( fileName, null );
-               
-                       WriteXmlSchema( writer );
+                       XmlTextWriter writer = new XmlTextWriter (fileName, null);
+                       try {
+                               writer.Formatting = Formatting.Indented;
+                               writer.WriteStartDocument (true);
+                               WriteXmlSchema (writer);
+                       } finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
-               public void WriteXmlSchema(TextWriter writer)
+               public void WriteXmlSchema (TextWriter writer)
                {
-                       XmlWriter xwriter = new XmlTextWriter( writer );
-                       
-                       WriteXmlSchema( xwriter );
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);
+                       try {
+                               xwriter.Formatting = Formatting.Indented;
+//                             xwriter.WriteStartDocument ();
+                               WriteXmlSchema (xwriter);
+                       } finally {
+//                             xwriter.WriteEndDocument ();
+                               xwriter.Close ();
+                       }
                }
 
-               public void WriteXmlSchema(XmlWriter writer)
+               public void WriteXmlSchema (XmlWriter writer)
                {
-                       ((XmlTextWriter)writer).Formatting = Formatting.Indented;
                        //Create a skeleton doc and then write the schema 
                        //proper which is common to the WriteXml method in schema mode
-                       writer.WriteStartDocument();
-                       
-                       DoWriteXmlSchema( writer );
-                       
-                       writer.WriteEndDocument();
+                       DoWriteXmlSchema (writer);
                }
 
-               public void ReadXmlSchema(Stream stream)
+               public void ReadXmlSchema (Stream stream)
                {
-                       XmlReader reader = new XmlTextReader( stream, null );
-                       ReadXmlSchemareader);
+                       XmlReader reader = new XmlTextReader (stream, null);
+                       ReadXmlSchema (reader);
                }
 
-               public void ReadXmlSchema(string str)
+               public void ReadXmlSchema (string str)
                {
-                       XmlReader reader = new XmlTextReader( str );
-                       ReadXmlSchema( reader );
+                       XmlReader reader = new XmlTextReader (str);
+                       try {
+                               ReadXmlSchema (reader);
+                       }
+                       finally {
+                               reader.Close ();
+                       }
                }
 
-               public void ReadXmlSchema(TextReader treader)
+               public void ReadXmlSchema (TextReader treader)
                {
-                       XmlReader reader = new XmlTextReader( treader );
-                       ReadXmlSchema( reader );                        
+                       XmlReader reader = new XmlTextReader (treader);
+                       ReadXmlSchema (reader);                 
                }
 
-               public void ReadXmlSchema(XmlReader reader)
+               public void ReadXmlSchema (XmlReader reader)
                {
+#if true
+                       new XmlSchemaDataImporter (this, reader).Process ();
+#else
                        XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
                        SchemaMapper.Read (reader);
+#endif
                }
 
                public XmlReadMode ReadXml (Stream stream)
@@ -512,7 +823,13 @@ namespace System.Data {
 
                public XmlReadMode ReadXml (string str)
                {
-                       return ReadXml (new XmlTextReader (str));
+                       XmlTextReader reader = new XmlTextReader (str);
+                       try {
+                               return ReadXml (reader);
+                       }
+                       finally {
+                               reader.Close ();
+                       }
                }
 
                public XmlReadMode ReadXml (TextReader reader)
@@ -522,33 +839,7 @@ namespace System.Data {
 
                public XmlReadMode ReadXml (XmlReader r)
                {
-                       XmlDataLoader Loader = new XmlDataLoader (this);
-                       // FIXME: somekinda exception?
-                       if (!r.Read ())
-                               return XmlReadMode.Auto; // FIXME
-
-                       /*\
-                        *  If document is diffgram we will use diffgram
-                       \*/
-                       if (r.LocalName == "diffgram")
-                               return ReadXml (r, XmlReadMode.DiffGram);
-
-                       /*\
-                        *  If we already have a schema, or the document 
-                        *  contains an in-line schema, sets XmlReadMode to ReadSchema.
-                       \*/
-
-                       // FIXME: is this always true: "if we have tables we have to have schema also"
-                       if (Tables.Count > 0)                           
-                               return ReadXml (r, XmlReadMode.ReadSchema);
-
-                       /*\
-                        *  If we dont have a schema yet and document 
-                        *  contains no inline-schema  mode is XmlReadMode.InferSchema
-                       \*/
-
-                       return ReadXml (r, XmlReadMode.InferSchema);
-
+                       return ReadXml (r, XmlReadMode.Auto);
                }
 
                public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
@@ -558,7 +849,13 @@ namespace System.Data {
 
                public XmlReadMode ReadXml (string str, XmlReadMode mode)
                {
-                       return ReadXml (new XmlTextReader (str), mode);
+                       XmlTextReader reader = new XmlTextReader (str);
+                       try {
+                               return ReadXml (reader, mode);
+                       }
+                       finally {
+                               reader.Close ();
+                       }
                }
 
                public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
@@ -566,24 +863,222 @@ namespace System.Data {
                        return ReadXml (new XmlTextReader (reader), mode);
                }
 
-               [MonoTODO]
-               public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
+               // LAMESPEC: XmlReadMode.Fragment is far from presisely
+               // documented. MS.NET infers schema against this mode.
+               public XmlReadMode ReadXml (XmlReader input, XmlReadMode mode)
                {
-                       XmlReadMode Result = XmlReadMode.Auto;
+                       switch (input.ReadState) {
+                       case ReadState.EndOfFile:
+                       case ReadState.Error:
+                       case ReadState.Closed:
+                               return mode;
+                       }
+                       // Skip XML declaration and prolog
+                       input.MoveToContent ();
+                       if (input.EOF)
+                               return mode;
+
+                       // FIXME: We need more decent code here, but for now
+                       // I don't know the precise MS.NET behavior, I just
+                       // delegate to specific read process.
+                       switch (mode) {
+                       case XmlReadMode.IgnoreSchema:
+                               return ReadXmlIgnoreSchema (input, mode, true);
+                       case XmlReadMode.ReadSchema:
+                               return ReadXmlReadSchema (input, mode, true);
+                       }
+                       // remaining modes are: Auto, InferSchema, Fragment, Diffgram
+
+                       XmlReader reader = input;
+
+                       int depth = reader.Depth;
+                       XmlReadMode result = mode;
+                       bool skippedTopLevelElement = false;
+                       string potentialDataSetName = null;
+                       XmlDocument doc = null;
+                       bool shouldReadData = mode != XmlReadMode.DiffGram;
+                       bool shouldNotInfer = Tables.Count > 0;
+
+                       switch (mode) {
+                       case XmlReadMode.Auto:
+                       case XmlReadMode.InferSchema:
+                               doc = new XmlDocument ();
+                               do {
+                                       doc.AppendChild (doc.ReadNode (reader));
+                               } while (!reader.EOF &&
+                                       doc.DocumentElement == null);
+                               reader = new XmlNodeReader (doc);
+                               reader.MoveToContent ();
+                               break;
+                       case XmlReadMode.DiffGram:
+                               if (!(reader.LocalName == "diffgram" &&
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace))
+                                       goto case XmlReadMode.Auto;
+                               break;
+                       }
 
-                       if (mode == XmlReadMode.DiffGram) {
-                               XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
-                               DiffLoader.Load (reader);
-                               Result =  XmlReadMode.DiffGram;
+                       switch (mode) {
+                       case XmlReadMode.Auto:
+                       case XmlReadMode.InferSchema:
+                       case XmlReadMode.ReadSchema:
+                               if (!(reader.LocalName == "diffgram" &&
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
+                                       !(reader.LocalName == "schema" &&
+                                       reader.NamespaceURI == XmlSchema.Namespace))
+                                       potentialDataSetName = reader.LocalName;
+                               goto default;
+                       case XmlReadMode.Fragment:
+                               break;
+                       default:
+                               if (!(reader.LocalName == "diffgram" &&
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
+                                       !(reader.LocalName == "schema" &&
+                                       reader.NamespaceURI == XmlSchema.Namespace)) {
+                                       if (!reader.IsEmptyElement) {
+                                               reader.Read ();
+                                               reader.MoveToContent ();
+                                               skippedTopLevelElement = true;
+                                       }
+                                       else {
+                                               switch (mode) {
+                                               case XmlReadMode.Auto:
+                                               case XmlReadMode.InferSchema:
+                                                       DataSetName = reader.LocalName;
+                                                       break;
+                                               }
+                                               reader.Read ();
+                                       }
+                               }
+                               break;
                        }
-                       else {
-                               XmlDataLoader Loader = new XmlDataLoader (this);
-                               Result = Loader.LoadData (reader, mode);
+
+                       // If schema, then read the first element as schema 
+                       if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
+                               shouldNotInfer = true;
+                               switch (mode) {
+                               case XmlReadMode.IgnoreSchema:
+                               case XmlReadMode.InferSchema:
+                                       reader.Skip ();
+                                       break;
+                               case XmlReadMode.Fragment:
+                                       ReadXmlSchema (reader);
+                                       break;
+                               case XmlReadMode.DiffGram:
+                               case XmlReadMode.Auto:
+                                       if (Tables.Count == 0) {
+                                               ReadXmlSchema (reader);
+                                               if (mode == XmlReadMode.Auto)
+                                                       result = XmlReadMode.ReadSchema;
+                                       } else {
+                                       // otherwise just ignore and return IgnoreSchema
+                                               reader.Skip ();
+                                               result = XmlReadMode.IgnoreSchema;
+                                       }
+                                       break;
+                               case XmlReadMode.ReadSchema:
+                                       ReadXmlSchema (reader);
+                                       break;
+                               }
                        }
 
-                       return Result;
-               }
+                       // If diffgram, then read the first element as diffgram 
+                       if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
+                               switch (mode) {
+                               case XmlReadMode.Auto:
+                               case XmlReadMode.IgnoreSchema:
+                               case XmlReadMode.DiffGram:
+                                       XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
+                                       DiffLoader.Load (reader);
+                                       if (mode == XmlReadMode.Auto)
+                                               result = XmlReadMode.DiffGram;
+                                       shouldReadData = false;
+                                       break;
+                               case XmlReadMode.Fragment:
+                                       reader.Skip ();
+                                       break;
+                               default:
+                                       reader.Skip ();
+                                       break;
+                               }
+                       }
+
+                       // if schema after diffgram, just skip it.
+                       if (!shouldReadData && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
+                               shouldNotInfer = true;
+                               switch (mode) {
+                               default:
+                                       reader.Skip ();
+                                       break;
+                               case XmlReadMode.ReadSchema:
+                               case XmlReadMode.DiffGram:
+                                       if (Tables.Count == 0)
+                                               ReadXmlSchema (reader);
+                                       break;
+                               }
+                       }
 
+                       if (reader.EOF)
+                               return result == XmlReadMode.Auto ?
+                                       potentialDataSetName != null && !shouldNotInfer ?
+                                       XmlReadMode.InferSchema :
+                                       XmlReadMode.IgnoreSchema : result;
+
+                       // Otherwise, read as dataset... but only when required.
+                       if (shouldReadData && !shouldNotInfer) {
+                               switch (mode) {
+                               case XmlReadMode.Auto:
+                                       if (Tables.Count > 0)
+                                               goto case XmlReadMode.IgnoreSchema;
+                                       else
+                                               goto case XmlReadMode.InferSchema;
+                               case XmlReadMode.InferSchema:
+                                       InferXmlSchema (doc, null);
+                                       if (mode == XmlReadMode.Auto)
+                                               result = XmlReadMode.InferSchema;
+                                       break;
+                               case XmlReadMode.IgnoreSchema:
+                               case XmlReadMode.Fragment:
+                               case XmlReadMode.DiffGram:
+                                       break;
+                               default:
+                                       shouldReadData = false;
+                                       break;
+                               }
+                       }
+
+                       if (shouldReadData) {
+                               XmlReader dataReader = reader;
+                               if (doc != null) {
+                                       dataReader = new XmlNodeReader (doc);
+                                       dataReader.MoveToContent ();
+                               }
+                               if (reader.NodeType == XmlNodeType.Element)
+                                       XmlDataReader.ReadXml (this, dataReader,
+                                               mode);
+                       }
+
+                       if (skippedTopLevelElement) {
+                               switch (result) {
+                               case XmlReadMode.Auto:
+                               case XmlReadMode.InferSchema:
+//                                     DataSetName = potentialDataSetName;
+//                                     result = XmlReadMode.InferSchema;
+                                       break;
+                               }
+                               if (reader.NodeType == XmlNodeType.EndElement)
+                                       reader.ReadEndElement ();
+                       }
+//*
+                       while (input.Depth > depth)
+                               input.Read ();
+                       if (input.NodeType == XmlNodeType.EndElement)
+                               input.Read ();
+//*/
+                       input.MoveToContent ();
+
+                       return result == XmlReadMode.Auto ?
+                               XmlReadMode.IgnoreSchema : result;
+               }
                #endregion // Public Methods
 
                #region Public Events
@@ -594,14 +1089,6 @@ namespace System.Data {
 
                #endregion // Public Events
 
-               #region Destructors
-
-               ~DataSet()
-               {
-               }
-
-               #endregion Destructors
-
                #region IListSource methods
                IList IListSource.GetList ()
                {
@@ -618,40 +1105,71 @@ namespace System.Data {
                #region ISupportInitialize methods
                public void BeginInit ()
                {
-                       throw new NotImplementedException ();
                }
                
                public void EndInit ()
                {
-                       throw new NotImplementedException ();
                }
                #endregion
 
                #region ISerializable
                void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
                {
-                       throw new NotImplementedException ();
+                       StringWriter sw = new StringWriter ();
+                       XmlTextWriter writer = new XmlTextWriter (sw);
+                       DoWriteXmlSchema (writer);
+                       writer.Flush ();
+                       si.AddValue ("XmlSchema", sw.ToString ());
+                       
+                       sw = new StringWriter ();
+                       writer = new XmlTextWriter (sw);
+                       WriteXml (writer, XmlWriteMode.DiffGram);
+                       writer.Flush ();
+                       si.AddValue ("XmlDiffGram", sw.ToString ());
                }
                #endregion
                
                #region Protected Methods
-               protected void GetSerializationData(SerializationInfo info, StreamingContext context)
+               protected void GetSerializationData (SerializationInfo info, StreamingContext context)
                {
-                       string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
-                       if (s != null) ReadXmlSerializable (new XmlTextReader(new StringReader(s)));
+                       string s = info.GetValue ("XmlSchema", typeof (String)) as String;
+                       XmlTextReader reader = new XmlTextReader (new StringReader (s));
+                       ReadXmlSchema (reader);
+                       reader.Close ();
+                       
+                       s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
+                       reader = new XmlTextReader (new StringReader (s));
+                       ReadXml (reader, XmlReadMode.DiffGram);
+                       reader.Close ();
                }
                
                
-               protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable()
+               protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
                {
-                       return null; // FIXME
+                       return null;
                }
                
-               protected virtual void ReadXmlSerializable(XmlReader reader)
+               protected virtual void ReadXmlSerializable (XmlReader reader)
                {
-                       ReadXml(reader, XmlReadMode.DiffGram); // FIXME
+                       ReadXml (reader);
+               }
+
+               void IXmlSerializable.ReadXml (XmlReader reader)
+               {
+                       ReadXmlSerializable(reader);
                }
                
+               void IXmlSerializable.WriteXml (XmlWriter writer)
+               {
+                       DoWriteXmlSchema (writer);
+                       WriteXml (writer, XmlWriteMode.DiffGram);
+               }
+
+               XmlSchema IXmlSerializable.GetSchema ()
+               {
+                       return GetSchemaSerializable ();
+               }
+
                protected virtual bool ShouldSerializeRelations ()
                {
                        return true;
@@ -663,7 +1181,7 @@ namespace System.Data {
                }
 
                [MonoTODO]
-               protected virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
+               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
                {
                }
 
@@ -677,58 +1195,138 @@ namespace System.Data {
                {
                }
 
+               internal virtual void OnMergeFailed (MergeFailedEventArgs e)
+               {
+                       if (MergeFailed != null)
+                               MergeFailed (this, e);
+               }
+
                [MonoTODO]
-               protected void RaisePropertyChanging (string name)
+               protected internal void RaisePropertyChanging (string name)
                {
                }
                #endregion
 
-               #region Private Xml Serialisation
+               #region Private Methods
+
+               private XmlReadMode ReadXmlIgnoreSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
+               {
+                       if (input.LocalName == "schema" &&
+                               input.NamespaceURI == XmlSchema.Namespace) {
+                               input.Skip ();
+                       }
+                       else if (input.LocalName == "diffgram" &&
+                               input.NamespaceURI == XmlConstants.DiffgrNamespace) {
+                               XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
+                               DiffLoader.Load (input);
+                       }
+                       else if (checkRecurse ||
+                               input.LocalName == DataSetName &&
+                               input.NamespaceURI == Namespace) {
+                               XmlDataReader.ReadXml (this, input, mode);
+                       }
+                       else if (checkRecurse && !input.IsEmptyElement) {
+                               int depth = input.Depth;
+                               input.Read ();
+                               input.MoveToContent ();
+                               ReadXmlIgnoreSchema (input, mode, false);
+                               while (input.Depth > depth)
+                                       input.Skip ();
+                               if (input.NodeType == XmlNodeType.EndElement)
+                                       input.ReadEndElement ();
+                       }
+                       input.MoveToContent ();
+                       return XmlReadMode.IgnoreSchema;
+               }
+
+               private XmlReadMode ReadXmlReadSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
+               {
+                       if (input.LocalName == "schema" &&
+                               input.NamespaceURI == XmlSchema.Namespace) {
+                               ReadXmlSchema (input);
+                       }
+                       else if (checkRecurse && !input.IsEmptyElement) {
+                               int depth = input.Depth;
+                               input.Read ();
+                               input.MoveToContent ();
+                               ReadXmlReadSchema (input, mode, false);
+                               while (input.Depth > depth)
+                                       input.Skip ();
+                               if (input.NodeType == XmlNodeType.EndElement)
+                                       input.ReadEndElement ();
+                       }
+                       else
+                               input.Skip ();
+                       input.MoveToContent ();
+                       return XmlReadMode.ReadSchema;
+               }
 
-               private string WriteObjectXml( object o ) {
+               private string WriteObjectXml (object o)
+               {
                        switch (Type.GetTypeCode (o.GetType ())) {
-                       case TypeCode.Boolean:
-                               return XmlConvert.ToString ((Boolean) o);
-                       case TypeCode.Byte:
-                               return XmlConvert.ToString ((Byte) o);
-                       case TypeCode.Char:
-                               return XmlConvert.ToString ((Char) o);
-                       case TypeCode.DateTime:
-                               return XmlConvert.ToString ((DateTime) o);
-                       case TypeCode.Decimal:
-                               return XmlConvert.ToString ((Decimal) o);
-                       case TypeCode.Double:
-                               return XmlConvert.ToString ((Double) o);
-                       case TypeCode.Int16:
-                               return XmlConvert.ToString ((Int16) o);
-                       case TypeCode.Int32:
-                               return XmlConvert.ToString ((Int32) o);
-                       case TypeCode.Int64:
-                               return XmlConvert.ToString ((Int64) o);
-                       case TypeCode.SByte:
-                               return XmlConvert.ToString ((SByte) o);
-                       case TypeCode.Single:
-                               return XmlConvert.ToString ((Single) o);
-                       case TypeCode.UInt16:
-                               return XmlConvert.ToString ((UInt16) o);
-                       case TypeCode.UInt32:
-                               return XmlConvert.ToString ((UInt32) o);
-                       case TypeCode.UInt64:
-                               return XmlConvert.ToString ((UInt64) o);
+                               case TypeCode.Boolean:
+                                       return XmlConvert.ToString ((Boolean) o);
+                               case TypeCode.Byte:
+                                       return XmlConvert.ToString ((Byte) o);
+                               case TypeCode.Char:
+                                       return XmlConvert.ToString ((Char) o);
+                               case TypeCode.DateTime:
+                                       return XmlConvert.ToString ((DateTime) o);
+                               case TypeCode.Decimal:
+                                       return XmlConvert.ToString ((Decimal) o);
+                               case TypeCode.Double:
+                                       return XmlConvert.ToString ((Double) o);
+                               case TypeCode.Int16:
+                                       return XmlConvert.ToString ((Int16) o);
+                               case TypeCode.Int32:
+                                       return XmlConvert.ToString ((Int32) o);
+                               case TypeCode.Int64:
+                                       return XmlConvert.ToString ((Int64) o);
+                               case TypeCode.SByte:
+                                       return XmlConvert.ToString ((SByte) o);
+                               case TypeCode.Single:
+                                       return XmlConvert.ToString ((Single) o);
+                               case TypeCode.UInt16:
+                                       return XmlConvert.ToString ((UInt16) o);
+                               case TypeCode.UInt32:
+                                       return XmlConvert.ToString ((UInt32) o);
+                               case TypeCode.UInt64:
+                                       return XmlConvert.ToString ((UInt64) o);
                        }
                        if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
                        if (o is Guid) return XmlConvert.ToString ((Guid) o);
-                       return o.ToString();
+                       if (o is byte[]) return Convert.ToBase64String ((byte[])o);
+                       return o.ToString ();
                }
-       
-               private void WriteTable( XmlWriter writer, DataTable table, XmlWriteMode mode )
+               
+               private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
+               {
+                       //Write out each table in order, providing it is not
+                       //part of another table structure via a nested parent relationship
+                       foreach (DataTable table in tableCollection) {
+                               bool isTopLevel = true;
+                               /*
+                               foreach (DataRelation rel in table.ParentRelations) {
+                                       if (rel.Nested) {
+                                               isTopLevel = false;
+                                               break;
+                                       }
+                               }
+                               */
+                               if (isTopLevel) {
+                                       WriteTable ( writer, table, mode, version);
+                               }
+                       }
+               }
+
+               private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
                {
                        DataRow[] rows = new DataRow [table.Rows.Count];
                        table.Rows.CopyTo (rows, 0);
-                       WriteTable (writer, rows, mode);
+                       WriteTable (writer, rows, mode, version, true);
                }
 
-               private void WriteTable( XmlWriter writer, DataRow[] rows, XmlWriteMode mode )
+               private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version, bool skipIfNested)
                {
                        //The columns can be attributes, hidden, elements, or simple content
                        //There can be 0-1 simple content cols or 0-* elements
@@ -738,18 +1336,51 @@ namespace System.Data {
 
                        if (rows.Length == 0) return;
                        DataTable table = rows[0].Table;
-                       SplitColumns( table, out atts, out elements, out simple );
-
-                       foreach( DataRow row in rows )
-                       {
-                               //sort out the namespacing
-                               string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
+                       SplitColumns (table, out atts, out elements, out simple);
+                       //sort out the namespacing
+                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
+                       int relationCount = table.ParentRelations.Count;
+                       DataRelation oneRel = relationCount == 1 ? table.ParentRelations [0] : null;
+
+                       foreach (DataRow row in rows) {
+                               if (skipIfNested) {
+                                       // Skip rows that is a child of any tables.
+                                       switch (relationCount) {
+                                       case 0:
+                                               break;
+                                       case 1:
+                                               if (!oneRel.Nested)
+                                                       break;
+                                               if (row.GetParentRow (oneRel) != null)
+                                                       continue;
+                                               break;
+                                       case 2:
+                                               bool skip = false;
+                                               for (int i = 0; i < table.ParentRelations.Count; i++) {
+                                                       DataRelation prel = table.ParentRelations [i];
+                                                       if (!prel.Nested)
+                                                               continue;
+                                                       if (row.GetParentRow (prel) != null) {
+                                                               skip = true;
+                                                               continue;
+                                                       }
+                                               }
+                                               if (skip)
+                                                       continue;
+                                               break;
+                                       }
+                               }
 
+                               if (!row.HasVersion(version) || 
+                                  (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged 
+                                     && version == DataRowVersion.Original))
+                                       continue;
+                               
                                // First check are all the rows null. If they are we just write empty element
                                bool AllNulls = true;
                                foreach (DataColumn dc in table.Columns) {
                                
-                                       if (row [dc.ColumnName] != DBNull.Value) {
+                                       if (row [dc.ColumnName, version] != DBNull.Value) {
                                                AllNulls = false;
                                                break;
                                        } 
@@ -757,326 +1388,669 @@ namespace System.Data {
 
                                // If all of the columns were null, we have to write empty element
                                if (AllNulls) {
-                                       writer.WriteElementString (table.TableName, "");
+                                       writer.WriteElementString (XmlConvert.EncodeLocalName (table.TableName), "");
                                        continue;
                                }
-
-                               WriteStartElement( writer, mode, nspc, table.Prefix, table.TableName );
                                
-                               foreach( DataColumn col in atts )
-                               {                                       
-                                       WriteAttributeString( writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col].ToString() );
-                               }
+                               WriteTableElement (writer, mode, table, row, version);
                                
-                               if( simple != null )
-                               {
-                                       writer.WriteString( WriteObjectXml(row[simple]) );
+                               foreach (DataColumn col in atts) {                                      
+                                       WriteColumnAsAttribute (writer, mode, col, row, version);
                                }
-                               else
-                               {                                       
-                                       foreach( DataColumn col in elements )
-                                       {
-                                               string colnspc = nspc;
-                                               object rowObject = row [col];
-                                                                                               
-                                               if (rowObject == null || rowObject == DBNull.Value)
-                                                       continue;
-
-                                               if( col.Namespace != null )
-                                               {
-                                                       colnspc = col.Namespace;
-                                               }
                                
-                                               //TODO check if I can get away with write element string
-                                               WriteStartElement( writer, mode, colnspc, col.Prefix, col.ColumnName );
-                                               writer.WriteString( WriteObjectXml(rowObject) );
-                                               writer.WriteEndElement();
+                               if (simple != null) {
+                                       writer.WriteString (WriteObjectXml (row[simple, version]));
+                               }
+                               else {                                  
+                                       foreach (DataColumn col in elements) {
+                                               WriteColumnAsElement (writer, mode, col, row, version);
                                        }
                                }
                                
                                foreach (DataRelation relation in table.ChildRelations) {
                                        if (relation.Nested) {
-                                               WriteTable (writer, row.GetChildRows(relation), mode);
+                                               WriteTable (writer, row.GetChildRows (relation), mode, version, false);
                                        }
                                }
                                
-                               writer.WriteEndElement();
+                               writer.WriteEndElement ();
                        }
 
                }
+
+               private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
+               {
+                       string colnspc = null;
+                       object rowObject = row [col, version];
+                                                                       
+                       if (rowObject == null || rowObject == DBNull.Value)
+                               return;
+
+                       if (col.Namespace != String.Empty)
+                               colnspc = col.Namespace;
+       
+                       //TODO check if I can get away with write element string
+                       WriteStartElement (writer, mode, colnspc, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName));
+                       writer.WriteString (WriteObjectXml (rowObject));
+                       writer.WriteEndElement ();
+               }
+
+               private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
+               {
+                       if (!row.IsNull (col))
+                               WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName), WriteObjectXml (row[col, version]));
+               }
+
+               private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
+               {
+                       //sort out the namespacing
+                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
+
+                       WriteStartElement (writer, mode, nspc, table.Prefix, XmlConvert.EncodeLocalName (table.TableName));
+
+                       if (mode == XmlWriteMode.DiffGram) {
+                               WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
+                               WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));
+                               string modeName = null;
+                               if (row.RowState == DataRowState.Modified)
+                                       modeName = "modified";
+                               else if (row.RowState == DataRowState.Added)
+                                       modeName = "inserted";
+
+                               if (version != DataRowVersion.Original && modeName != null)
+                                       WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
+                       }
+               }
                    
-               private void WriteStartElement( XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name )
-               {                       
-                       switch(  mode )
-                               {
-                                       case XmlWriteMode.WriteSchema:
-                                               if( nspc == null || nspc == "" )
-                                               {
-                                                       writer.WriteStartElement( name );
-                                               }
-                                               else if( prefix != null )
-                                               {                                                       
-                                                       writer.WriteStartElement(prefix, name, nspc );
-                                               }                                               
-                                               else
-                                               {                                       
-                                                       writer.WriteStartElement( writer.LookupPrefix( nspc ), name, nspc );
-                                               }
-                                               break;
-                                       case XmlWriteMode.DiffGram:
-                                               throw new NotImplementedException();
-                                       default:                                               
-                                               writer.WriteStartElement(name );
-                                               break;                                  
-                               };
+               private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
+               {
+                       writer.WriteStartElement (prefix, name, nspc);
                }
                
-               private void WriteAttributeString( XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue )
-               {
-                       switch(  mode )
-                               {
-                                       case XmlWriteMode.WriteSchema:
-                                               writer.WriteAttributeString(prefix, name, nspc );
-                                               break;
-                                       case XmlWriteMode.DiffGram:
-                                               throw new NotImplementedException();                            
-                                       default:
-                                               writer.WriteAttributeString(name, stringValue );
-                                               break;                                  
-                               };
+               private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
+               {
+                       switch ( mode) {
+                               case XmlWriteMode.WriteSchema:
+                                       writer.WriteAttributeString (prefix, name, nspc);
+                                       break;
+                               case XmlWriteMode.DiffGram:
+                                       writer.WriteAttributeString (prefix, name, nspc,stringValue);
+                                       break;
+                               default:
+                                       writer.WriteAttributeString (name, stringValue);
+                                       break;                                  
+                       };
                }
                
-               private void DoWriteXmlSchema( XmlWriter writer )
-               {
-                       //Create the root element and declare all the namespaces etc
-                       writer.WriteStartElement(XmlConstants.SchemaPrefix, XmlConstants.SchemaElement,
-                                                                               XmlConstants.SchemaNamespace );
-                       writer.WriteAttributeString( XmlConstants.TargetNamespace, Namespace );
-                       writer.WriteAttributeString( "xmlns:" + XmlConstants.TnsPrefix, Namespace );
-                       writer.WriteAttributeString( "xmlns", Namespace );
-                       writer.WriteAttributeString(  "xmlns:" + XmlConstants.MsdataPrefix,                 
-                                                   XmlConstants.MsdataNamespace );
-                       //Set up the attribute and element forms.  
-                       //TODO - is it possible to change this?
-                       //I couldn't spot if it was so I assumed
-                       //that this is set to qualified all round basedon the MS output
-                       writer.WriteAttributeString( XmlConstants.AttributeFormDefault, 
-                                                   XmlConstants.Qualified );
-                       writer.WriteAttributeString( XmlConstants.ElementFormDefault, 
-                                                   XmlConstants.Qualified );
-                       
-                       
-                       //<xs:element name="DSName msdata:IsDataSet="true" msdata:Locale="machine-locale">
-                       //Create the data set element
-                       //All the tables are represented as choice elements in an unlimited series
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                       XmlConstants.Element,
-                                                       XmlConstants.SchemaNamespace );
-                       
-                       writer.WriteAttributeString( XmlConstants.Name, DataSetName );
-                       writer.WriteAttributeString( XmlConstants.MsdataPrefix,  XmlConstants.IsDataSet, XmlConstants.MsdataNamespace, "true" );
-                       //FIXME - sort out the locale string!
+               internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
+               {
+                       ((XmlTextWriter)writer).Formatting = Formatting.Indented;
 
-                       writer.WriteAttributeString( XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace, Thread.CurrentThread.CurrentCulture.Name);
+                       if (mode == XmlWriteMode.DiffGram) {
+                               SetTableRowsID (table);
+                               WriteDiffGramElement (writer);
+                       }
                        
-                       //<xs:complexType>
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                       XmlConstants.ComplexType,
-                                                       XmlConstants.SchemaNamespace );
+                       WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
                        
-                       //<xs:choice maxOccurs="unbounded">
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                       XmlConstants.Choice,
-                                                       XmlConstants.SchemaNamespace );
+                       WriteTable (writer, table, mode, DataRowVersion.Default);
                        
-                       writer.WriteAttributeString( XmlConstants.MaxOccurs, XmlConstants.Unbounded );
+                       if (mode == XmlWriteMode.DiffGram) {
+                               writer.WriteEndElement (); //DataSet name
+                               if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
+
+                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);   
+                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
+                                       WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
+                                       writer.WriteEndElement ();
+                               }
+                       }
+                       writer.WriteEndElement (); // DataSet name or diffgr:diffgram
+               }
+               
+
+               private void CheckNamespace (string prefix, string ns, XmlNamespaceManager nsmgr, XmlSchema schema)
+               {
+                       if (ns == String.Empty)
+                               return;
+                       if (ns != nsmgr.DefaultNamespace) {
+                               if (nsmgr.LookupNamespace (nsmgr.NameTable.Get (prefix)) != ns) {
+                                       for (int i = 1; i < int.MaxValue; i++) {
+                                               string p = nsmgr.NameTable.Add ("app" + i);
+                                               if (!nsmgr.HasNamespace (p)) {
+                                                       nsmgr.AddNamespace (p, ns);
+                                                       HandleExternalNamespace (p, ns, schema);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               XmlSchema BuildSchema ()
+               {
+                       return BuildSchema (Tables, Relations);
+               }
+               
+               internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
+               {
+                       string constraintPrefix = "";
+                       XmlSchema schema = new XmlSchema ();
+                       XmlNamespaceManager nsmgr = new XmlNamespaceManager (new NameTable ());
                        
+                       if (Namespace != "") {
+                               schema.AttributeFormDefault = XmlSchemaForm.Qualified;
+                               schema.ElementFormDefault = XmlSchemaForm.Qualified;
+                               schema.TargetNamespace = Namespace;
+                               constraintPrefix = XmlConstants.TnsPrefix + ":";
+                       }
+
+                       // set the schema id
+                       schema.Id = DataSetName;
+                       XmlDocument doc = new XmlDocument ();
+                       XmlAttribute attr = null;
+                       ArrayList atts = new ArrayList ();
+
+                       attr = doc.CreateAttribute ("", "xmlns", XmlConstants.XmlnsNS);
+                       atts.Add (attr);
+
+                       nsmgr.AddNamespace ("xs", XmlSchema.Namespace);
+                       nsmgr.AddNamespace (XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
+                       if (Namespace != "") {
+                               nsmgr.AddNamespace (XmlConstants.TnsPrefix, Namespace);
+                               nsmgr.AddNamespace (String.Empty, Namespace);
+                       }
+                       if (CheckExtendedPropertyExists (tables, relations))
+                               nsmgr.AddNamespace (XmlConstants.MspropPrefix, XmlConstants.MspropNamespace);
+
+                       if (atts.Count > 0)
+                               schema.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+
+                       XmlSchemaElement elem = new XmlSchemaElement ();
+                       elem.Name = XmlConvert.EncodeName (DataSetName);
+
+                       // Add namespaces used in DataSet components (tables, columns, ...)
+                       foreach (DataTable dt in tables) {
+                               foreach (DataColumn col in dt.Columns)
+                                       CheckNamespace (col.Prefix, col.Namespace, nsmgr, schema);
+                               CheckNamespace (dt.Prefix, dt.Namespace, nsmgr, schema);
+                       }
+
+                       // Attributes for DataSet element
+                       atts.Clear ();
+                       attr = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
+                       attr.Value = "true";
+                       atts.Add (attr);
+
+                       attr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
+                       attr.Value = locale.Name;
+                       atts.Add (attr);
+
+                       elem.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+
+                       AddExtendedPropertyAttributes (elem, ExtendedProperties, doc);
+
+                       XmlSchemaComplexType complex = new XmlSchemaComplexType ();
+                       elem.SchemaType = complex;
+
+                       XmlSchemaChoice choice = new XmlSchemaChoice ();
+                       complex.Particle = choice;
+                       choice.MaxOccursString = XmlConstants.Unbounded;
                        
-                       //Write out schema for each table in order, providing it is not
-                       //part of another table structure via a nested parent relationship
-                       foreach( DataTable table in Tables )
-                       {               
+                       //Write out schema for each table in order
+                       foreach (DataTable table in tables) {           
                                bool isTopLevel = true;
-                               foreach( DataRelation rel in table.ParentRelations )
-                               {
-                                       if( rel.Nested )
-                                       {
+                               foreach (DataRelation rel in table.ParentRelations) {
+                                       if (rel.Nested) {
                                                isTopLevel = false;
                                                break;
                                        }
                                }
                                
-                               if( isTopLevel )
-                               {
-                                       WriteTableSchema(  writer, table );
+                               if (isTopLevel) {
+                                       if (table.Namespace != SafeNS (schema.TargetNamespace)) {
+                                               XmlSchemaElement extElem = new XmlSchemaElement ();
+                                               extElem.RefName = new XmlQualifiedName (table.TableName, table.Namespace);
+                                               choice.Items.Add (extElem);
+                                       }
+                                       else
+                                               choice.Items.Add (GetTableSchema (doc, table, schema, nsmgr));
                                }
                        }
+
+                       schema.Items.Add (elem);
                        
-                       //</xs:choice>
-                       writer.WriteEndElement();
-                       //</xs:complexType>
-                       writer.WriteEndElement();
-                       
-                       //TODO - now add in the relationships as key and unique constraints etc
-                       
-                       //</xs:element>
-                       writer.WriteEndElement();
-                       
-                       
-                       //</schema>
-                       writer.WriteEndElement();
+                       AddConstraintsToSchema (elem, constraintPrefix, tables, relations, doc);
+                       foreach (string prefix in nsmgr) {
+                               string ns = nsmgr.LookupNamespace (nsmgr.NameTable.Get (prefix));
+                               if (prefix != "xmlns" && prefix != "xml" && ns != null && ns != String.Empty)
+                                       schema.Namespaces.Add (prefix, ns);
+                       }
+
+                       return schema;
+               }
+
+               private bool CheckExtendedPropertyExists (
+                       DataTableCollection tables,
+                       DataRelationCollection relations)
+               {
+                       if (ExtendedProperties.Count > 0)
+                               return true;
+                       foreach (DataTable dt in tables) {
+                               if (dt.ExtendedProperties.Count > 0)
+                                       return true;
+                               foreach (DataColumn col in dt.Columns)
+                                       if (col.ExtendedProperties.Count > 0)
+                                               return true;
+                               foreach (Constraint c in dt.Constraints)
+                                       if (c.ExtendedProperties.Count > 0)
+                                               return true;
+                       }
+                       if (relations == null)
+                               return false;
+                       foreach (DataRelation rel in relations)
+                               if (rel.ExtendedProperties.Count > 0)
+                                       return true;
+                       return false;
+               }
+
+               // Add all constraints in all tables to the schema.
+               private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations, XmlDocument doc) 
+               {
+                       // first add all unique constraints.
+                       Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables, doc);
+                       // Add all foriegn key constraints.
+                       AddForeignKeys (uniqueNames, elem, constraintPrefix, relations, doc);
+               }
+               
+               // Add unique constaraints to the schema.
+               // return hashtable with the names of all XmlSchemaUnique elements we created.
+               private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, XmlDocument doc)
+               {
+                       Hashtable uniqueNames = new Hashtable();
+                       foreach (DataTable table in tables) {
+                               
+                               foreach (Constraint constraint in table.Constraints) {
+                                       
+                                       if (constraint is UniqueConstraint) {
+                                               ArrayList attrs = new ArrayList ();
+                                               XmlAttribute attrib;
+                                               UniqueConstraint uqConst = (UniqueConstraint) constraint;
+                                               XmlSchemaUnique uniq = new XmlSchemaUnique ();
+                                               
+                                               // if column of the constraint is hidden do not write the constraint.
+                                               bool isHidden = false;
+                                               foreach (DataColumn column in uqConst.Columns) {
+                                                       if (column.ColumnMapping == MappingType.Hidden) {
+                                                               isHidden = true;
+                                                               break;
+                                                       }
+                                               }
+
+                                               if (isHidden)
+                                                       continue;
+
+                                               // if constaraint name do not exist in the hashtable we can use it.
+                                               if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
+                                                       uniq.Name = uqConst.ConstraintName;
+                                               }
+                                               // generate new constraint name for the XmlSchemaUnique element.
+                                               else {
+                                                       uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
+                                                       attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
+                                                       attrib.Value = uqConst.ConstraintName;
+                                                       attrs.Add (attrib);
+                                               }
+                                               if (uqConst.IsPrimaryKey) {
+                                                       attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
+                                                       attrib.Value = "true";
+                                                       attrs.Add (attrib);
+                                               }
+               
+                                               uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
+
+                                               uniq.Selector = new XmlSchemaXPath();
+                                               uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
+                                               XmlSchemaXPath field;
+                                               foreach (DataColumn column in uqConst.Columns) {
+                                                       field = new XmlSchemaXPath();
+                                                       string typePrefix = column.ColumnMapping == MappingType.Attribute ? "@" : "";
+                                                       field.XPath = typePrefix + constraintPrefix+column.ColumnName;
+                                                       uniq.Fields.Add(field);
+                                               }
+                               
+                                               AddExtendedPropertyAttributes (uniq, constraint.ExtendedProperties, doc);
+
+                                               elem.Constraints.Add (uniq);
+                                               uniqueNames.Add (uniq.Name, null);
+                                       }
+                               }
+                       }
+                       return uniqueNames;
                }
                
-               private void WriteTableSchema( XmlWriter writer, DataTable table )
+               // Add the foriegn keys to the schema.
+               private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations, XmlDocument doc)
+               {
+                       if (relations == null) return;
+                       
+                       foreach (DataRelation rel in relations) {
+                               
+                               if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
+                                       continue;
+
+                               bool isHidden = false;
+                               foreach (DataColumn col in rel.ParentColumns) {
+                                       if (col.ColumnMapping == MappingType.Hidden) {
+                                               isHidden = true;
+                                               break;
+                                       }
+                               }
+                               foreach (DataColumn col in rel.ChildColumns) {
+                                       if (col.ColumnMapping == MappingType.Hidden) {
+                                               isHidden = true;
+                                               break;
+                                       }
+                               }
+                               if (isHidden)
+                                       continue;
+                               
+                               ArrayList attrs = new ArrayList ();
+                               XmlAttribute attrib;
+                               XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
+                               keyRef.Name = rel.RelationName;
+                               ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
+                               UniqueConstraint uqConst = rel.ParentKeyConstraint;
+                               
+                               string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
+                               // first try to find the concatenated name. If we didn't find it - use constraint name.
+                               if (uniqueNames.ContainsKey (concatName)) {
+                                       keyRef.Refer = new XmlQualifiedName(concatName);
+                               }
+                               else {
+                                       keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
+                               }
+
+                               if (rel.Nested) {
+                                       attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsNested, XmlConstants.MsdataNamespace);
+                                       attrib.Value = "true";
+                                       attrs.Add (attrib);
+                               }
+
+                               keyRef.Selector = new XmlSchemaXPath();
+                               keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
+                               XmlSchemaXPath field;
+                               foreach (DataColumn column in rel.ChildColumns) {
+                                       field = new XmlSchemaXPath();
+                                       string typePrefix = column.ColumnMapping == MappingType.Attribute ? "@" : "";
+                                       field.XPath = typePrefix + constraintPrefix + column.ColumnName;
+                                       keyRef.Fields.Add(field);
+                               }
+
+                               keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
+                               AddExtendedPropertyAttributes (keyRef, rel.ExtendedProperties, doc);
+
+                               elem.Constraints.Add (keyRef);
+                       }
+               }
+
+               private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table, XmlSchema schemaToAdd, XmlNamespaceManager nsmgr)
                {
                        ArrayList elements;
                        ArrayList atts;
                        DataColumn simple;
-                       
-                       SplitColumns( table,out  atts, out elements, out simple );
-                       
-                       //<xs:element name="TableName">
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                XmlConstants.Element,
-                                                XmlConstants.SchemaNamespace );
-                       
-                       writer.WriteAttributeString( XmlConstants.Name, table.TableName );
-                       
-                       //<xs:complexType>
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                XmlConstants.ComplexType,
-                                                XmlConstants.SchemaNamespace );
-                       
-                       //TODO - what about the simple content?
-                       if( elements.Count == 0 )                               
-                       {                               
-                       }
-                       else
-                       {                               
-                       //A sequence of element types or a simple content node
-                       //<xs:sequence>
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                XmlConstants.Sequence,
-                                                XmlConstants.SchemaNamespace );
-                       foreach( DataColumn col in elements )
-                       {
-                               //<xs:element name=ColumnName type=MappedType Ordinal=index>
-                               writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                XmlConstants.Element,
-                                                XmlConstants.SchemaNamespace );
+
+                       ArrayList xattrs = new ArrayList();
+                       XmlAttribute xattr;
+
+                       SplitColumns (table, out atts, out elements, out simple);
+
+                       XmlSchemaElement elem = new XmlSchemaElement ();
+                       elem.Name = table.TableName;
+
+                       XmlSchemaComplexType complex = new XmlSchemaComplexType ();
+                       elem.SchemaType = complex;
+
+                       XmlSchemaObjectCollection schemaAttributes = null;
+
+                       if (simple != null) {
+                               // add simpleContent
+                               XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
+                               complex.ContentModel = simpleContent;
+
+                               // add column name attribute
+                               XmlAttribute[] xlmAttrs = new XmlAttribute [2];
+                               xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
+                               xlmAttrs[0].Value = simple.ColumnName;
+                               
+                               // add ordinal attribute
+                               xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
+                               xlmAttrs[1].Value = XmlConvert.ToString (simple.Ordinal);
+                               simpleContent.UnhandledAttributes = xlmAttrs;
                                
-                               writer.WriteAttributeString( XmlConstants.Name, col.ColumnName );
+                               
+                               // add extension
+                               XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
+                               simpleContent.Content = extension;
+                               extension.BaseTypeName = MapType (simple.DataType);
+                               schemaAttributes = extension.Attributes;
+                       } else {
+                               schemaAttributes = complex.Attributes;
+                               //A sequence of element types or a simple content node
+                               //<xs:sequence>
+                               XmlSchemaSequence seq = new XmlSchemaSequence ();
+
+                               foreach (DataColumn col in elements) {
+                                       
+                                       // Add element for the column.
+                                       XmlSchemaElement colElem = new XmlSchemaElement ();
+                                       colElem.Name = col.ColumnName;
                                
-                               if (col.ColumnName != col.Caption && col.Caption != string.Empty)
-                                       writer.WriteAttributeString( XmlConstants.MsdataPrefix, XmlConstants.Caption, 
-                                                                    XmlConstants.MsdataNamespace, col.Caption); 
+                                       if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
+                                               xattr.Value = col.Caption;
+                                               xattrs.Add (xattr);
+                                       }
+
+                                       if (col.AutoIncrement == true) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
+                                               xattr.Value = "true";
+                                               xattrs.Add (xattr);
+                                       }
 
-                               if (col.DefaultValue.ToString () != string.Empty)
-                                       writer.WriteAttributeString( XmlConstants.Default, col.DefaultValue.ToString ());
+                                       if (col.AutoIncrementSeed != 0) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
+                                               xattr.Value = XmlConvert.ToString (col.AutoIncrementSeed);
+                                               xattrs.Add (xattr);
+                                       }
 
-                               writer.WriteAttributeString( XmlConstants.Type, MapType( col.DataType ) );
+                                       if (col.DefaultValue.ToString () != String.Empty)
+                                               colElem.DefaultValue = WriteObjectXml (col.DefaultValue);
 
-                               if( col.AllowDBNull )
-                               {
-                                       writer.WriteAttributeString( XmlConstants.MinOccurs, "0" );
-                               }
+                                       if (col.ReadOnly) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ReadOnly, XmlConstants.MsdataNamespace);
+                                               xattr.Value = "true";
+                                               xattrs.Add (xattr);
+                                       }
 
-                               //writer.WriteAttributeString( XmlConstants.MsdataPrefix,
-                               //                            XmlConstants.Ordinal,
-                               //                            XmlConstants.MsdataNamespace,
-                               //                            col.Ordinal.ToString() );
+                                       if (col.MaxLength < 0)
+                                               colElem.SchemaTypeName = MapType (col.DataType);
+                                       
+                                       if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string) 
+                                               && col.DataType != typeof (char)) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
+                                               xattr.Value = col.DataType.AssemblyQualifiedName;
+                                               xattrs.Add (xattr);
+                                       }
 
-                               // Write SimpleType if column have MaxLength
-                               if (col.MaxLength > -1) {
+                                       if (col.AllowDBNull) {
+                                               colElem.MinOccurs = 0;
+                                       }
+
+                                       //writer.WriteAttributeString (XmlConstants.MsdataPrefix, 
+                                       //                            XmlConstants.Ordinal, 
+                                       //                            XmlConstants.MsdataNamespace, 
+                                       //                            col.Ordinal.ToString ());
 
-                                       WriteTableSimpleType (writer, col);
+                                       // Write SimpleType if column have MaxLength
+                                       if (col.MaxLength > -1) {
+                                               colElem.SchemaType = GetTableSimpleType (doc, col);
+                                       }
+                                       
+                                       colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
+                                       xattrs.Clear ();
+                                       AddExtendedPropertyAttributes (colElem, col.ExtendedProperties, doc);
+                                       seq.Items.Add (colElem);
                                }
-                               
 
-                               //</xs:element>
-                               writer.WriteEndElement();
-                       }
-                       //</xs:sequence>
-                       writer.WriteEndElement();
-                               
+                               foreach (DataRelation rel in table.ChildRelations) {
+                                       if (rel.Nested) {
+                                               if (rel.ChildTable.Namespace != SafeNS (schemaToAdd.TargetNamespace)) {
+                                                       XmlSchemaElement el = new XmlSchemaElement ();
+                                                       el.RefName = new XmlQualifiedName (rel.ChildTable.TableName, rel.ChildTable.Namespace);
+                                               } else {
+                                                       XmlSchemaElement el = GetTableSchema (doc, rel.ChildTable, schemaToAdd, nsmgr);
+                                                       el.MinOccurs = 0;
+                                                       el.MaxOccursString = "unbounded";
+                                                       XmlSchemaComplexType ct = (XmlSchemaComplexType) el.SchemaType;
+                                                       ct.Name = el.Name;
+                                                       el.SchemaType = null;
+                                                       el.SchemaTypeName = new XmlQualifiedName (ct.Name, schemaToAdd.TargetNamespace);
+                                                       schemaToAdd.Items.Add (ct);
+                                                       seq.Items.Add (el);
+                                               }
+                                       }
+                               }
+
+                               if (seq.Items.Count > 0)
+                                       complex.Particle = seq;
                        }
+
                        //Then a list of attributes
-                       foreach( DataColumn col in atts )
-                       {
+                       foreach (DataColumn col in atts) {
                                //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
-                               writer.WriteStartElement( XmlConstants.SchemaPrefix,
-                                                XmlConstants.Attribute,
-                                                XmlConstants.SchemaNamespace );
-                               
-                               writer.WriteAttributeString( XmlConstants.Name, col.ColumnName );
-                               writer.WriteAttributeString( XmlConstants.Form, XmlConstants.Unqualified );
-                               writer.WriteAttributeString( XmlConstants.Type, MapType( col.DataType ) );
-                               
-                               writer.WriteEndElement();
+                               XmlSchemaAttribute att = new XmlSchemaAttribute ();
+                               att.Name = col.ColumnName;
+                               if (col.Namespace != String.Empty) {
+                                       att.Form = XmlSchemaForm.Qualified;
+                                       string prefix = col.Prefix == String.Empty ? "app" + schemaToAdd.Namespaces.Count : col.Prefix;
+                                       att.Name = prefix + ":" + col.ColumnName;
+                                       // FIXME: Handle prefix mapping correctly.
+                                       schemaToAdd.Namespaces.Add (prefix, col.Namespace);
+                               }
+                               if (!col.AllowDBNull)
+                                       att.Use = XmlSchemaUse.Required;
+                               if (col.DefaultValue.ToString () != String.Empty)
+                                       att.DefaultValue = WriteObjectXml (col.DefaultValue);
+
+                               if (col.ReadOnly) {
+                                       xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ReadOnly, XmlConstants.MsdataNamespace);
+                                       xattr.Value = "true";
+                                       xattrs.Add (xattr);
+                               }
+
+                               att.UnhandledAttributes = xattrs.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+                               xattrs.Clear ();
+
+                               if (col.MaxLength > -1)
+                                       att.SchemaType = GetTableSimpleType (doc, col);
+                               else
+                                       att.SchemaTypeName = MapType (col.DataType);
+                               // FIXME: what happens if extended properties are set on attribute columns??
+                               schemaAttributes.Add (att);
                        }
-                       
-                       //</xs:complexType>
-                       writer.WriteEndElement();
-                       
-                       //</xs:element>
-                       writer.WriteEndElement();
+
+                       AddExtendedPropertyAttributes (elem, table.ExtendedProperties, doc);
+
+                       return elem;
+               }
+
+               private void AddExtendedPropertyAttributes (XmlSchemaAnnotated xsobj, PropertyCollection props, XmlDocument doc)
+               {
+                       ArrayList attList = new ArrayList ();
+                       XmlAttribute xmlAttr;
+
+                       if (xsobj.UnhandledAttributes != null)
+                               attList.AddRange (xsobj.UnhandledAttributes);
+
+                       // add extended properties to xs:element
+                       foreach (DictionaryEntry de in props) {
+                               xmlAttr = doc.CreateAttribute (XmlConstants.MspropPrefix, XmlConvert.EncodeName (de.Key.ToString ()), XmlConstants.MspropNamespace);
+                               xmlAttr.Value = de.Value != null ? WriteObjectXml (de.Value) : String.Empty;
+                               attList.Add (xmlAttr);
+                       }
+                       if (attList.Count > 0)
+                               xsobj.UnhandledAttributes = attList.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
                }
 
-               private void WriteTableSimpleType (XmlWriter writer, DataColumn col)
+               private string SafeNS (string ns)
+               {
+                       return ns != null ? ns : String.Empty;
+               }
+
+               private void HandleExternalNamespace (string prefix, string ns, XmlSchema schema)
+               {
+                       foreach (XmlSchemaExternal ext in schema.Includes) {
+                               XmlSchemaImport imp = ext as XmlSchemaImport;
+                               if (imp != null && imp.Namespace == ns)
+                                       return; // nothing to do
+                       }
+                       XmlSchemaImport i = new XmlSchemaImport ();
+                       i.Namespace = ns;
+                       i.SchemaLocation = "_" + prefix + ".xsd";
+                       schema.Includes.Add (i);
+               }
+
+               private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
                {
                        // SimpleType
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix, XmlConstants.SimpleType, 
-                                                 XmlConstants.SchemaNamespace);
-                       
+                       XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
+
                        // Restriction
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix, XmlConstants.Restriction, 
-                                                 XmlConstants.SchemaNamespace);
-                       
-                       writer.WriteAttributeString( XmlConstants.Base, MapType( col.DataType ) );
+                       XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
+                       restriction.BaseTypeName = MapType (col.DataType);
                        
                        // MaxValue
-                       writer.WriteStartElement( XmlConstants.SchemaPrefix, XmlConstants.MaxLength, 
-                                                 XmlConstants.SchemaNamespace);
-                       writer.WriteAttributeString( XmlConstants.Value, col.MaxLength.ToString ());
-                       
+                       XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
+                       max.Value = XmlConvert.ToString (col.MaxLength);
+                       restriction.Facets.Add (max);
                        
-                       writer.WriteEndElement();
-                       
-                       writer.WriteEndElement();
-                       
-                       writer.WriteEndElement();
+                       simple.Content = restriction;
+                       return simple;
                }
 
+               private void DoWriteXmlSchema (XmlWriter writer)
+               {
+                       BuildSchema ().Write (writer);
+               }
+               
                ///<summary>
                /// Helper function to split columns into attributes elements and simple
                /// content
                /// </summary>
-               private void SplitColumns(      DataTable table,
-                                                                       out ArrayList atts,
-                                                                       out ArrayList elements,
-                                                                       out DataColumn simple)
+               private void SplitColumns (DataTable table, 
+                       out ArrayList atts, 
+                       out ArrayList elements, 
+                       out DataColumn simple)
                {
                        //The columns can be attributes, hidden, elements, or simple content
                        //There can be 0-1 simple content cols or 0-* elements
-                       atts = new System.Collections.ArrayList();
-                       elements = new System.Collections.ArrayList();
+                       atts = new System.Collections.ArrayList ();
+                       elements = new System.Collections.ArrayList ();
                        simple = null;
                        
                        //Sort out the columns
-                       foreach( DataColumn col in table.Columns )
-                       {
-                               switch( col.ColumnMapping )
-                               {
+                       foreach (DataColumn col in table.Columns) {
+                               switch (col.ColumnMapping) {
                                        case MappingType.Attribute:
-                                               atts.Add( col );
+                                               atts.Add (col);
                                                break;
                                        case MappingType.Element:
-                                               elements.Add( col );
+                                               elements.Add (col);
                                                break;
                                        case MappingType.SimpleContent:
-                                               if( simple != null )
-                                               {
-                                                       throw new System.InvalidOperationException( "There may only be one simple content element" );
+                                               if (simple != null) {
+                                                       throw new System.InvalidOperationException ("There may only be one simple content element");
                                                }
                                                simple = col;
                                                break;
@@ -1086,50 +2060,61 @@ namespace System.Data {
                                }
                        }
                }
+
+               private void WriteDiffGramElement(XmlWriter writer)
+               {
+                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
+                       WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
+               }
+
+               private void SetRowsID()
+               {
+                       foreach (DataTable Table in Tables)
+                               SetTableRowsID (Table);
+               }
                
-               [MonoTODO]
-               private string MapType( Type type )
-               {
-                       string Result = "xs:string";
-
-                       // TODO: More types to map?
-
-                       if (typeof (string) == type)
-                               Result = "xs:string";
-                       else if (typeof (short) == type)
-                               Result = "xs:short";
-                       else if (typeof (int) == type)
-                               Result = "xs:int";
-                       else if (typeof (long) == type)
-                               Result = "xs:long";
-                       else if (typeof (bool) == type)
-                               Result = "xs:boolean";
-                       else if (typeof (byte) == type)
-                               Result = "xs:unsignedByte";
-                       else if (typeof (char) == type)
-                               Result = "xs:char";
-                       else if (typeof (DateTime) == type)
-                               Result = "xs:dateTime";
-                       else if (typeof (decimal) == type)
-                               Result = "xs:decimal";
-                       else if (typeof (double) == type)
-                               Result = "xs:double";
-                       else if (typeof (sbyte) == type)
-                               Result = "xs:sbyte";
-                       else if (typeof (Single) == type)
-                               Result = "xs:float";
-                       else if (typeof (TimeSpan) == type)
-                               Result = "xs:duration";
-                       else if (typeof (ushort) == type)
-                               Result = "xs:usignedShort";
-                       else if (typeof (uint) == type)
-                               Result = "xs:unsignedInt";
-                       else if (typeof (ulong) == type)
-                               Result = "xs:unsignedLong";
-               
-                       return Result;
+               private void SetTableRowsID (DataTable Table)
+               {
+                       int dataRowID = 0;
+                       foreach (DataRow Row in Table.Rows) {
+                               Row.XmlRowID = dataRowID;
+                               dataRowID++;
+                       }
                }
+
                
+               private XmlQualifiedName MapType (Type type)
+               {
+                       switch (Type.GetTypeCode (type)) {
+                               case TypeCode.String: return XmlConstants.QnString;
+                               case TypeCode.Int16: return XmlConstants.QnShort;
+                               case TypeCode.Int32: return XmlConstants.QnInt;
+                               case TypeCode.Int64: return XmlConstants.QnLong;
+                               case TypeCode.Boolean: return XmlConstants.QnBoolean;
+                               case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
+                               //case TypeCode.Char: return XmlConstants.QnChar;
+                               case TypeCode.DateTime: return XmlConstants.QnDateTime;
+                               case TypeCode.Decimal: return XmlConstants.QnDecimal;
+                               case TypeCode.Double: return XmlConstants.QnDouble;
+                               case TypeCode.SByte: return XmlConstants.QnSbyte;
+                               case TypeCode.Single: return XmlConstants.QnFloat;
+                               case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
+                               case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
+                               case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
+                       }
+                       
+                       if (typeof (TimeSpan) == type)
+                               return XmlConstants.QnDuration;
+                       else if (typeof (System.Uri) == type)
+                               return XmlConstants.QnUri;
+                       else if (typeof (byte[]) == type)
+                               return XmlConstants.QnBase64Binary;
+                       else if (typeof (XmlQualifiedName) == type)
+                               return XmlConstants.QnXmlQualifiedName;
+                       else
+                               return XmlConstants.QnString;
+               }
+
                #endregion //Private Xml Serialisation
        }
 }