2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Data / System.Data / DataSet.cs
index f83d7d5146efc60f7d777c7887316180e4f6cee8..17815bb815c8470fbe16b9a96b5177be529e6eb6 100644 (file)
@@ -8,11 +8,35 @@
 //   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, 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;
 using System.Collections;
 using System.ComponentModel;
@@ -29,6 +53,8 @@ namespace System.Data {
 
        [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, IXmlSerializable 
@@ -43,6 +69,7 @@ namespace System.Data {
                private PropertyCollection properties;
                private DataViewManager defaultView;
                private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
+               internal XmlDataDocument _xmlDataDocument = null;
                
                #region Constructors
 
@@ -61,10 +88,9 @@ namespace System.Data {
                        this.Locale = CultureInfo.CurrentCulture;
                }
 
-               [MonoTODO]
                protected DataSet (SerializationInfo info, StreamingContext context) : this ()
                {
-                       throw new NotImplementedException ();
+                       GetSerializationData (info, context);
                }
 
                #endregion // Constructors
@@ -79,11 +105,6 @@ namespace System.Data {
                                return caseSensitive;
                        } 
                        set {
-                               foreach (DataTable T in Tables) {
-                                       if (T.VirginCaseSensitive)
-                                               T.CaseSensitive = value;
-                               }
-
                                caseSensitive = value; 
                                if (!caseSensitive) {
                                        foreach (DataTable table in Tables) {
@@ -233,12 +254,14 @@ namespace System.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;
                        }
                }
 
@@ -246,11 +269,16 @@ 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;
@@ -302,22 +330,34 @@ namespace System.Data {
                                tempTable.AcceptChanges ();
                }
 
+                /// <summary>
+                /// Clears all the tables
+                /// </summary>
                public void Clear ()
                {
-                       // TODO: if currently bound to a XmlDataDocument
-                       //       throw a NotSupportedException
-                       for (int t = 0; t < tableCollection.Count; t++) {
+                       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 ()
                {
-                       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
@@ -344,7 +384,6 @@ namespace System.Data {
                        return Copy;
                }
 
-               [MonoTODO]
                private void CopyProperties (DataSet Copy)
                {
                        Copy.CaseSensitive = CaseSensitive;
@@ -353,12 +392,17 @@ 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.Site = Site;
+                       //Copy.Site = Site; // FIXME : Not sure of this.
 
                }
                
@@ -452,13 +496,13 @@ namespace System.Data {
                        }
                
                        DataRow newRow = copyTable.NewRow ();
-                       copyTable.Rows.Add (newRow);
                        row.CopyValuesToRow (newRow);
+                       copyTable.Rows.Add (newRow);
                        newRow.XmlRowID = row.XmlRowID;
                        addedRows.Add (row,row);
                }
 
-#if NET_1_2
+#if NET_2_0
                [MonoTODO]
                public DataTableReader GetDataReader (DataTable[] dataTables)
                {
@@ -475,9 +519,7 @@ namespace System.Data {
                public string GetXml ()
                {
                        StringWriter Writer = new StringWriter ();
-
-                       // Sending false for not printing the Processing instruction
-                       WriteXml (Writer, XmlWriteMode.IgnoreSchema, false);
+                       WriteXml (Writer, XmlWriteMode.IgnoreSchema);
                        return Writer.ToString ();
                }
 
@@ -518,9 +560,18 @@ namespace System.Data {
                        return false;           
                }
 
-               [MonoTODO]
                public void InferXmlSchema (XmlReader reader, string[] nsArray)
                {
+                       if (reader == null)
+                               return;
+                       XmlDocument doc = new XmlDocument ();
+                       doc.Load (reader);
+                       InferXmlSchema (doc, nsArray);
+               }
+
+               private void InferXmlSchema (XmlDocument doc, string [] nsArray)
+               {
+                       XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
                }
 
                public void InferXmlSchema (Stream stream, string[] nsArray)
@@ -543,7 +594,7 @@ namespace System.Data {
                        }
                }
 
-#if NET_1_2
+#if NET_2_0
                [MonoTODO]
                public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
                {
@@ -603,9 +654,14 @@ namespace System.Data {
                {
                        XmlTextWriter writer = new XmlTextWriter (fileName, null);
                        writer.Formatting = Formatting.Indented;
-                       WriteXml (writer);
-                       
-                       writer.Close ();
+                       writer.WriteStartDocument (true);
+                       try {
+                               WriteXml (writer);
+                       }
+                       finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
                public void WriteXml (TextWriter writer)
@@ -617,95 +673,74 @@ namespace System.Data {
 
                public void WriteXml (XmlWriter writer)
                {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
                }
 
                public void WriteXml (string filename, XmlWriteMode mode)
                {
                        XmlTextWriter writer = new XmlTextWriter (filename, null);
                        writer.Formatting = Formatting.Indented;
-                       WriteXml (writer, mode, true);
+                       writer.WriteStartDocument (true);
+                       
+                       try {
+                               WriteXml (writer, mode);
+                       }
+                       finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
                public void WriteXml (Stream stream, XmlWriteMode mode)
                {
                        XmlTextWriter writer = new XmlTextWriter (stream, null);
                        writer.Formatting = Formatting.Indented;
-                       WriteXml (writer, mode, true);
+                       WriteXml (writer, mode);
                }
 
                public void WriteXml (TextWriter writer, XmlWriteMode mode)
                {
                        XmlTextWriter xwriter = new XmlTextWriter (writer);
                        xwriter.Formatting = Formatting.Indented;
-                       WriteXml (xwriter, mode, true);
+                       WriteXml (xwriter, mode);
                }
 
                public void WriteXml (XmlWriter writer, XmlWriteMode mode)
                {
-                       WriteXml (writer, mode, true);
-               }
-               
-               internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (stream, null);
-                       writer.Formatting = Formatting.Indented;
-                       WriteXml (writer, mode, writePI);
-               }
-
-               internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (fileName, null);
-                       writer.Formatting = Formatting.Indented;
-                       WriteXml (writer, mode, writePI);
-                       
-                       writer.Close ();
-               }
-
-               internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
-               {
-                       XmlTextWriter xwriter = new XmlTextWriter (writer);
-                       xwriter.Formatting = Formatting.Indented;
-                       WriteXml (xwriter, mode, writePI);
-               }
-
-               internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
-               {
-                       if (writePI && (writer.WriteState == WriteState.Start))
-                               writer.WriteStartDocument (true);
-
                        if (mode == XmlWriteMode.DiffGram) {
                                SetRowsID();
                                WriteDiffGramElement(writer);
                        }
                        
-                       WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
-                       
-                       /*********************************************************
-                        * This is a patch for interoperability with ms.net.     *
-                        * Because in web services the .net client expects this  *
-                        * atrribute even if namespace is an empty string        *
-                        ********************************************************/
-                       if (Namespace == null || Namespace.Length == 0)
-                               WriteAttributeString (writer, mode, null, null, "xmlns", Namespace);
-                       
-                       
-                       if (mode == XmlWriteMode.WriteSchema) {
-                               DoWriteXmlSchema (writer);
+                       // 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);
+                               
+                               WriteTables (writer, mode, Tables, DataRowVersion.Default);
+                               writer.WriteEndElement ();
                        }
                        
-                       WriteTables (writer, mode, Tables, DataRowVersion.Default);
                        if (mode == XmlWriteMode.DiffGram) {
-                               writer.WriteEndElement (); //DataSet name
                                if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
 
-                                       DataSet beforeDS = GetChanges (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 (); // DataSet name or diffgr:diffgram
+                       
+                       if (mode == XmlWriteMode.DiffGram)
+                               writer.WriteEndElement (); // diffgr:diffgram
+
+                       writer.Flush ();
                }
 
                public void WriteXmlSchema (Stream stream)
@@ -718,25 +753,34 @@ namespace System.Data {
                public void WriteXmlSchema (string fileName)
                {
                        XmlTextWriter writer = new XmlTextWriter (fileName, null);
-                       writer.Formatting = Formatting.Indented;
-                       WriteXmlSchema (writer);
+                       try {
+                               writer.Formatting = Formatting.Indented;
+                               writer.WriteStartDocument (true);
+                               WriteXmlSchema (writer);
+                       } finally {
+                               writer.WriteEndDocument ();
+                               writer.Close ();
+                       }
                }
 
                public void WriteXmlSchema (TextWriter writer)
                {
                        XmlTextWriter xwriter = new XmlTextWriter (writer);
-                       xwriter.Formatting = Formatting.Indented;
-                       WriteXmlSchema (xwriter);
+                       try {
+                               xwriter.Formatting = Formatting.Indented;
+//                             xwriter.WriteStartDocument ();
+                               WriteXmlSchema (xwriter);
+                       } finally {
+//                             xwriter.WriteEndDocument ();
+                               xwriter.Close ();
+                       }
                }
 
                public void WriteXmlSchema (XmlWriter writer)
                {
                        //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 ();
                }
 
                public void ReadXmlSchema (Stream stream)
@@ -748,7 +792,12 @@ namespace System.Data {
                public void ReadXmlSchema (string str)
                {
                        XmlReader reader = new XmlTextReader (str);
-                       ReadXmlSchema (reader);
+                       try {
+                               ReadXmlSchema (reader);
+                       }
+                       finally {
+                               reader.Close ();
+                       }
                }
 
                public void ReadXmlSchema (TextReader treader)
@@ -759,8 +808,12 @@ namespace System.Data {
 
                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)
@@ -770,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)
@@ -780,71 +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
-                       
-                       // Check if the curent element is the process instruction (PI).
-                       // if it is move to next element.
-                       if (r.LocalName == "xml")
-                               r.MoveToContent();
-
-                       // The document can be diffgram if :
-                       // 1. The first element is diffgram.
-                       if (r.LocalName == "diffgram") {
-                               return ReadXml (r, XmlReadMode.DiffGram);
-                       }
-
-                       bool schemaRead = false;
-                       if (r.LocalName == "schema") {
-                               ReadXmlSchema (r);
-                               r.MoveToContent();
-                               schemaRead = true;
-                       }
-                       
-                       // If we read the schema the next element can be a diffgram
-                       // that is what happen in web services soap message.
-                       if (schemaRead && r.LocalName == "diffgram") {
-                               return ReadXml (r, XmlReadMode.DiffGram);
-                       }
-                       
-                       // Get the DataSet name.
-                       // if this xml is not diffgram then the first element will be the 
-                       // DataSet name.
-                       string dataSetName = XmlConvert.DecodeName (r.LocalName);
-                       DataSetName = dataSetName;
-                       
-                       r.ReadStartElement ();
-                       r.MoveToContent();
-                       
-                       
-                       // After reading the dataset name there can be three scenarios:
-                       // 1. The next part will be the schema of the dataset.
-                       // 2. The next part will be the data of the dataset using diffgram.
-                       // 3. The next part will be the data of tha dataset without diffgram.
-                       // Check if the current element is the schema
-                       if (r.LocalName == "schema") {
-                               ReadXmlSchema (r);
-                               r.MoveToContent();
-                               schemaRead = true;
-                       }
-                       
-                       // check if the data was written in a diffgram mode.
-                       if (r.LocalName == "diffgram") {
-                               return ReadXml (r, XmlReadMode.DiffGram);
-                       }
-                       
-                       // If the schema has been read we should read the rest data of the dataset
-                       // with ignoreschema mode.
-                       if (schemaRead) {
-                               ReadXml (r, XmlReadMode.IgnoreSchema, false);
-                               return XmlReadMode.ReadSchema;
-                       }
-                       
-                       // Read the data of the dataset with inferschema.
-                       return ReadXml (r, XmlReadMode.InferSchema, false);
-
+                       return ReadXml (r, XmlReadMode.Auto);
                }
 
                public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
@@ -854,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)
@@ -862,59 +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)
                {
-                       // we have to initiate the reader.
-                       if (reader.ReadState == ReadState.Initial)
-                               reader.Read();
-                       
-                       // Check if the curent element is the process instruction (PI).
-                       // if it is move to next element.
-                       if (reader.LocalName == "xml")
-                               reader.MoveToContent();
+                       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;
+                       }
 
-                       XmlReadMode Result = XmlReadMode.Auto;
+                       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;
+                       }
 
-                       if (mode == XmlReadMode.DiffGram) {
-                               if (reader.LocalName != "diffgram"){
-                                       reader.MoveToContent ();
-                                       reader.ReadStartElement ();     // <DataSet>
+                       // 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;
+                               }
+                       }
+
+                       // 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;
+                               }
+                       }
 
-                                       reader.MoveToContent ();
-                                       if (reader.LocalName == "schema")
+                       // 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;
+                               }
+                       }
 
-                                       reader.MoveToContent ();
+                       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;
                                }
-                               XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
-                               DiffLoader.Load (reader);
-                               Result =  XmlReadMode.DiffGram;
                        }
-                       else 
-                               Result = ReadXml(reader, mode, true);
 
-                       return Result;
-               }
+                       if (shouldReadData) {
+                               XmlReader dataReader = reader;
+                               if (doc != null) {
+                                       dataReader = new XmlNodeReader (doc);
+                                       dataReader.MoveToContent ();
+                               }
+                               if (reader.NodeType == XmlNodeType.Element)
+                                       XmlDataReader.ReadXml (this, dataReader,
+                                               mode);
+                       }
 
-               private XmlReadMode ReadXml (XmlReader r, XmlReadMode mode, bool readDataSet) {
-                       
-                       if (readDataSet) {
-                               string dataSetName = XmlConvert.DecodeName (r.LocalName);
-                               DataSetName = dataSetName;
-                               // get the Namespace of the DataSet.
-                               string tmp = r.GetAttribute("xmlns");
-                               if (tmp != null)
-                                       Namespace = tmp;
-                               
-                               r.ReadStartElement ();
-                               r.MoveToContent();
+                       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 ();
 
-                       XmlDataLoader Loader = new XmlDataLoader (this);
-                       return Loader.LoadData (r, mode);
+                       return result == XmlReadMode.Auto ?
+                               XmlReadMode.IgnoreSchema : result;
                }
-
                #endregion // Public Methods
 
                #region Public Events
@@ -925,14 +1089,6 @@ namespace System.Data {
 
                #endregion // Public Events
 
-               #region Destructors
-
-               ~DataSet ()
-               {
-               }
-
-               #endregion Destructors
-
                #region IListSource methods
                IList IListSource.GetList ()
                {
@@ -959,15 +1115,32 @@ namespace System.Data {
                #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)
                {
-                       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 ();
                }
                
                
@@ -978,23 +1151,23 @@ namespace System.Data {
                
                protected virtual void ReadXmlSerializable (XmlReader reader)
                {
-                       ReadXml (reader, XmlReadMode.DiffGram); // FIXME
+                       ReadXml (reader);
                }
 
                void IXmlSerializable.ReadXml (XmlReader reader)
                {
-
                        ReadXmlSerializable(reader);
-                       
-                       // the XmlSerializationReader does this lines!!!
-                       //reader.MoveToContent ();
-                       //reader.ReadEndElement ();     // </DataSet>
                }
                
                void IXmlSerializable.WriteXml (XmlWriter writer)
                {
                        DoWriteXmlSchema (writer);
-                       WriteXml (writer, XmlWriteMode.DiffGram, true);
+                       WriteXml (writer, XmlWriteMode.DiffGram);
+               }
+
+               XmlSchema IXmlSerializable.GetSchema ()
+               {
+                       return GetSchemaSerializable ();
                }
 
                protected virtual bool ShouldSerializeRelations ()
@@ -1022,7 +1195,7 @@ namespace System.Data {
                {
                }
 
-               protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
+               internal virtual void OnMergeFailed (MergeFailedEventArgs e)
                {
                        if (MergeFailed != null)
                                MergeFailed (this, e);
@@ -1034,7 +1207,59 @@ namespace System.Data {
                }
                #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)
                {
@@ -1070,6 +1295,7 @@ namespace System.Data {
                        }
                        if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
                        if (o is Guid) return XmlConvert.ToString ((Guid) o);
+                       if (o is byte[]) return Convert.ToBase64String ((byte[])o);
                        return o.ToString ();
                }
                
@@ -1079,13 +1305,14 @@ namespace System.Data {
                        //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);
                                }
@@ -1096,10 +1323,10 @@ namespace System.Data {
                {
                        DataRow[] rows = new DataRow [table.Rows.Count];
                        table.Rows.CopyTo (rows, 0);
-                       WriteTable (writer, rows, mode, version);
+                       WriteTable (writer, rows, mode, version, true);
                }
 
-               private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
+               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
@@ -1112,8 +1339,38 @@ namespace System.Data {
                        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))
@@ -1131,7 +1388,7 @@ 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;
                                }
                                
@@ -1146,13 +1403,13 @@ namespace System.Data {
                                }
                                else {                                  
                                        foreach (DataColumn col in elements) {
-                                               WriteColumnAsElement (writer, mode, nspc, col, row, version);
+                                               WriteColumnAsElement (writer, mode, col, row, version);
                                        }
                                }
                                
                                foreach (DataRelation relation in table.ChildRelations) {
                                        if (relation.Nested) {
-                                               WriteTable (writer, row.GetChildRows (relation), mode, version);
+                                               WriteTable (writer, row.GetChildRows (relation), mode, version, false);
                                        }
                                }
                                
@@ -1161,27 +1418,27 @@ namespace System.Data {
 
                }
 
-               private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
+               private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
                {
-                       string colnspc = nspc;
+                       string colnspc = null;
                        object rowObject = row [col, version];
                                                                        
                        if (rowObject == null || rowObject == DBNull.Value)
                                return;
 
-                       if (col.Namespace != null) {
+                       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, col.ColumnName);
+                       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)
                {
-                       WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
+                       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)
@@ -1189,11 +1446,11 @@ namespace System.Data {
                        //sort out the namespacing
                        string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
 
-                       WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
+                       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", row.XmlRowID.ToString());
+                               WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));
                                string modeName = null;
                                if (row.RowState == DataRowState.Modified)
                                        modeName = "modified";
@@ -1207,15 +1464,7 @@ namespace System.Data {
                    
                private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
                {
-                       if (nspc == null || nspc == "") {
-                               writer.WriteStartElement (name);
-                       }
-                       else if (prefix != null) {
-                               writer.WriteStartElement (prefix, name, nspc);
-                       }
-                       else {
-                               writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
-                       }
+                       writer.WriteStartElement (prefix, name, nspc);
                }
                
                private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
@@ -1258,10 +1507,24 @@ namespace System.Data {
                        }
                        writer.WriteEndElement (); // DataSet name or diffgr:diffgram
                }
+               
 
-               XmlSchema IXmlSerializable.GetSchema ()
+               private void CheckNamespace (string prefix, string ns, XmlNamespaceManager nsmgr, XmlSchema schema)
                {
-                       return BuildSchema ();
+                       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 ()
@@ -1273,38 +1536,59 @@ namespace System.Data {
                {
                        string constraintPrefix = "";
                        XmlSchema schema = new XmlSchema ();
-
-                       schema.Namespaces.Add("xs", XmlSchema.Namespace);
-                       schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
+                       XmlNamespaceManager nsmgr = new XmlNamespaceManager (new NameTable ());
                        
-                       if (Namespace != "" && Namespace != null) {
+                       if (Namespace != "") {
                                schema.AttributeFormDefault = XmlSchemaForm.Qualified;
                                schema.ElementFormDefault = XmlSchemaForm.Qualified;
                                schema.TargetNamespace = Namespace;
-                               schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
                                constraintPrefix = XmlConstants.TnsPrefix + ":";
                        }
-                               
+
                        // set the schema id
                        schema.Id = DataSetName;
                        XmlDocument doc = new XmlDocument ();
-                       XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
-                       xmlnsAttr.Value = Namespace;
+                       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 [];
 
-                       schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
-                                               
                        XmlSchemaElement elem = new XmlSchemaElement ();
                        elem.Name = XmlConvert.EncodeName (DataSetName);
 
-                       XmlAttribute[] atts = new XmlAttribute [2];
-                       atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
-                       atts[0].Value = "true";
+                       // 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);
+                       }
 
-                       atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
-                       atts[1].Value = locale.Name;
-                       elem.UnhandledAttributes = atts;
+                       // Attributes for DataSet element
+                       atts.Clear ();
+                       attr = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
+                       attr.Value = "true";
+                       atts.Add (attr);
 
-                       schema.Items.Add (elem);
+                       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;
@@ -1323,38 +1607,75 @@ namespace System.Data {
                                        }
                                }
                                
-                               if (isTopLevel){
-                                       choice.Items.Add (GetTableSchema (doc, 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);
                        
-                       AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
+                       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) 
+               private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations, XmlDocument doc
                {
                        // first add all unique constraints.
-                       Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
+                       Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables, doc);
                        // Add all foriegn key constraints.
-                       AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
+                       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)
+               private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, XmlDocument doc)
                {
-                       XmlDocument doc = new XmlDocument();
                        Hashtable uniqueNames = new Hashtable();
                        foreach (DataTable table in tables) {
                                
-                               foreach (Constraint constaint in table.Constraints) {
+                               foreach (Constraint constraint in table.Constraints) {
                                        
-                                       if (constaint is UniqueConstraint) {
+                                       if (constraint is UniqueConstraint) {
                                                ArrayList attrs = new ArrayList ();
                                                XmlAttribute attrib;
-                                               UniqueConstraint uqConst = (UniqueConstraint)constaint;
+                                               UniqueConstraint uqConst = (UniqueConstraint) constraint;
                                                XmlSchemaUnique uniq = new XmlSchemaUnique ();
                                                
                                                // if column of the constraint is hidden do not write the constraint.
@@ -1393,10 +1714,13 @@ namespace System.Data {
                                                XmlSchemaXPath field;
                                                foreach (DataColumn column in uqConst.Columns) {
                                                        field = new XmlSchemaXPath();
-                                                       field.XPath = constraintPrefix+column.ColumnName;
+                                                       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);
                                        }
@@ -1406,15 +1730,30 @@ namespace System.Data {
                }
                
                // Add the foriegn keys to the schema.
-               private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
+               private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations, XmlDocument doc)
                {
                        if (relations == null) return;
                        
-                       XmlDocument doc = new XmlDocument();
                        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;
@@ -1443,20 +1782,27 @@ namespace System.Data {
                                XmlSchemaXPath field;
                                foreach (DataColumn column in rel.ChildColumns) {
                                        field = new XmlSchemaXPath();
-                                       field.XPath = constraintPrefix+column.ColumnName;
+                                       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)
+               private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table, XmlSchema schemaToAdd, XmlNamespaceManager nsmgr)
                {
                        ArrayList elements;
                        ArrayList atts;
                        DataColumn simple;
-                       
+
+                       ArrayList xattrs = new ArrayList();
+                       XmlAttribute xattr;
+
                        SplitColumns (table, out atts, out elements, out simple);
 
                        XmlSchemaElement elem = new XmlSchemaElement ();
@@ -1465,7 +1811,8 @@ namespace System.Data {
                        XmlSchemaComplexType complex = new XmlSchemaComplexType ();
                        elem.SchemaType = complex;
 
-                       //TODO - what about the simple content?
+                       XmlSchemaObjectCollection schemaAttributes = null;
+
                        if (simple != null) {
                                // add simpleContent
                                XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
@@ -1478,7 +1825,7 @@ namespace System.Data {
                                
                                // add ordinal attribute
                                xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
-                               xlmAttrs[1].Value = simple.Ordinal.ToString();
+                               xlmAttrs[1].Value = XmlConvert.ToString (simple.Ordinal);
                                simpleContent.UnhandledAttributes = xlmAttrs;
                                
                                
@@ -1486,20 +1833,17 @@ namespace System.Data {
                                XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
                                simpleContent.Content = extension;
                                extension.BaseTypeName = MapType (simple.DataType);
-                       
-                       }
-                       else {
+                               schemaAttributes = extension.Attributes;
+                       } else {
+                               schemaAttributes = complex.Attributes;
                                //A sequence of element types or a simple content node
                                //<xs:sequence>
                                XmlSchemaSequence seq = new XmlSchemaSequence ();
-                               complex.Particle = seq;
 
                                foreach (DataColumn col in elements) {
                                        
                                        // Add element for the column.
                                        XmlSchemaElement colElem = new XmlSchemaElement ();
-                                       ArrayList xattrs = new ArrayList();
-                                       XmlAttribute xattr;
                                        colElem.Name = col.ColumnName;
                                
                                        if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
@@ -1516,20 +1860,26 @@ namespace System.Data {
 
                                        if (col.AutoIncrementSeed != 0) {
                                                xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
-                                               xattr.Value = col.AutoIncrementSeed.ToString();
+                                               xattr.Value = XmlConvert.ToString (col.AutoIncrementSeed);
                                                xattrs.Add (xattr);
                                        }
 
                                        if (col.DefaultValue.ToString () != String.Empty)
-                                               colElem.DefaultValue = col.DefaultValue.ToString ();
-                                       
+                                               colElem.DefaultValue = WriteObjectXml (col.DefaultValue);
+
+                                       if (col.ReadOnly) {
+                                               xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ReadOnly, XmlConstants.MsdataNamespace);
+                                               xattr.Value = "true";
+                                               xattrs.Add (xattr);
+                                       }
+
                                        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.ToString();
+                                               xattr.Value = col.DataType.AssemblyQualifiedName;
                                                xattrs.Add (xattr);
                                        }
 
@@ -1548,14 +1898,32 @@ namespace System.Data {
                                        }
                                        
                                        colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
+                                       xattrs.Clear ();
+                                       AddExtendedPropertyAttributes (colElem, col.ExtendedProperties, doc);
                                        seq.Items.Add (colElem);
                                }
 
                                foreach (DataRelation rel in table.ChildRelations) {
                                        if (rel.Nested) {
-                                               seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
+                                               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
@@ -1563,14 +1931,76 @@ namespace System.Data {
                                //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
                                XmlSchemaAttribute att = new XmlSchemaAttribute ();
                                att.Name = col.ColumnName;
-                               att.Form = XmlSchemaForm.Unqualified;
-                               att.SchemaTypeName = MapType (col.DataType);
-                               complex.Attributes.Add (att);
+                               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);
                        }
 
+                       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 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