[Mono-dev] [PATCH] DataTable.WriteXml

Nagappan anagappan at novell.com
Fri Oct 6 06:10:59 EDT 2006


Hi Patrick,
The patch looks fine, but it doesn't apply with the latest SVN. Can you
make a new patch and send it across.

Thanks
Nagappan

Patrick Earl wrote:
> I've implemented the WriteXml method for System.Data.DataTable. Since
> writing a table is similar to writing a DataSet, it leverages many of
> the methods used to write DataSets. Included with the patch are a
> successful unit test for the new WriteXml functionality and a failing
> unit test for ReadXml, which has not yet been implemented. The patch
> caused no regressions in the System.Data net_2_0 test suite.
>
> The patch applies against the mcs/class/System.Data folder in the
> latest SVN revision (66162 as of this message).
>
> This is my first substantial contribution, so I'm happy to get
> feedback on it. Thanks.
>
> Patrick Earl
> ------------------------------------------------------------------------
>
> Index: Test/System.Data/ChangeLog
> ===================================================================
> --- Test/System.Data/ChangeLog	(revision 66162)
> +++ Test/System.Data/ChangeLog	(working copy)
> @@ -1,3 +1,9 @@
> +2006-09-28  Patrick Earl <mono at patearl.net>
> +
> +	* DataTableReadWriteXml.cs: Added new tests for the DataTable's
> +	ReadXml and WriteXml methods.  These tests assume proper
> +	functioning of the DataSet ReadXml and WriteXml methods.
> +
>  2006-09-18	Boris Kirzner <borisk at mainsoft.com>
>  
>  	* DataViewTest.cs : fix compilation error.
> Index: Test/System.Data/DataTableReadWriteXmlTest.cs
> ===================================================================
> --- Test/System.Data/DataTableReadWriteXmlTest.cs	(revision 0)
> +++ Test/System.Data/DataTableReadWriteXmlTest.cs	(revision 0)
> @@ -0,0 +1,373 @@
> +// Author:
> +//   Patrick Earl <mono at patearl.net>
> +//
> +// Copyright (c) 2006
> +//
> +// 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.
> +//
> +
> +#if NET_2_0
> +using System;
> +using System.Data;
> +using System.IO;
> +using System.Text.RegularExpressions;
> +using System.Xml;
> +using NUnit.Framework; 
> +
> +namespace MonoTests.System.Data
> +{
> +    [TestFixture]
> +    public class DataTableReadWriteXmlTest
> +    {
> +        void StandardizeXmlFormat(ref string xml)
> +        {
> +            XmlDocument doc = new XmlDocument();
> +            doc.LoadXml(xml);
> +            StringWriter sw = new StringWriter();
> +            doc.Save(sw);
> +            xml = sw.ToString();
> +        }
> +        
> +        void GenerateTestData(out DataSet ds,
> +                              out DataTable dtMainInDS,
> +                              out DataTable dtChildInDS,
> +                              out DataTable dtMain)
> +        {
> +            ds = new DataSet("MyDataSet");
> +
> +            // Create a primary table and populate it with some data.  Make a
> +            // copy of the primary table and put it into the dataset.
> +            dtMain = new DataTable("Main");
> +            dtMain.Columns.Add(new DataColumn("ID", typeof(int)));
> +            dtMain.Columns.Add(new DataColumn("Data", typeof(string)));
> +            
> +            DataRow row = dtMain.NewRow();
> +            row["ID"] = 1;
> +            row["Data"] = "One";
> +            dtMain.Rows.Add(row);
> +            
> +            row = dtMain.NewRow();
> +            row["ID"] = 2;
> +            row["Data"] = "Two";
> +            dtMain.Rows.Add(row);
> +            
> +            row = dtMain.NewRow();
> +            row["ID"] = 3;
> +            row["Data"] = "Three";
> +            dtMain.Rows.Add(row);
> +            
> +            dtMainInDS = dtMain.Copy();
> +            ds.Tables.Add(dtMainInDS);
> +            
> +            // Create a child table.  Make a copy of the child table and put
> +            // it into the dataset.
> +            dtChildInDS = new DataTable("Child");
> +            dtChildInDS.Columns.Add(new DataColumn("ID", typeof(int)));
> +            dtChildInDS.Columns.Add(new DataColumn("PID", typeof(int)));
> +            dtChildInDS.Columns.Add(new DataColumn("ChildData", typeof(string)));
> +            
> +            row = dtChildInDS.NewRow();
> +            row["ID"] = 1;
> +            row["PID"] = 1;
> +            row["ChildData"] = "Parent1Child1";
> +            dtChildInDS.Rows.Add(row);
> +            
> +            row = dtChildInDS.NewRow();
> +            row["ID"] = 2;
> +            row["PID"] = 1;
> +            row["ChildData"] = "Parent1Child2";
> +            dtChildInDS.Rows.Add(row);
> +            
> +            row = dtChildInDS.NewRow();
> +            row["ID"] = 3;
> +            row["PID"] = 2;
> +            row["ChildData"] = "Parent2Child3";
> +            dtChildInDS.Rows.Add(row);
> +            
> +            ds.Tables.Add(dtChildInDS);
> +            
> +            // Set up the relation in the dataset.
> +            ds.Relations.Add(new DataRelation("MainToChild",
> +                                              dtMainInDS.Columns["ID"],
> +                                              dtChildInDS.Columns["PID"]));
> +        }
> +        
> +        [Test]
> +        public void TestWriteXml()
> +        {
> +            DataSet ds;
> +            DataTable dtMainInDS, dtChildInDS, dtMain;
> +            
> +            GenerateTestData(out ds,
> +                             out dtMainInDS,
> +                             out dtChildInDS,
> +                             out dtMain);
> +            
> +            StringWriter sw = new StringWriter();
> +            
> +            // Get XML for DataSet writes.
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw);
> +            string xmlDSNone = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw, XmlWriteMode.DiffGram);
> +            string xmlDSDiffGram = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            string xmlDSWriteSchema = sw.ToString();
> +
> +            // Get XML for recursive DataTable writes of the same data as in
> +            // the DataSet.
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, true);
> +            string xmlDTNone = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
> +            string xmlDTDiffGram = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
> +            string xmlDTWriteSchema = sw.ToString();
> +            
> +            // The schema XML written by the DataTable call has an extra element
> +            // in the element for the dataset schema definition.  We remove that
> +            // extra attribute and then check to see if the rest of the xml is
> +            // identical.
> +            XmlDocument doc = new XmlDocument();
> +            doc.LoadXml(xmlDTWriteSchema);
> +            XmlNode node = doc.DocumentElement.FirstChild.FirstChild;
> +            XmlAttribute a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
> +            Assert.IsNotNull(a, "Test#01");
> +            Assert.AreEqual("Main", a.Value, "Test#02");
> +            
> +            node.Attributes.Remove(a);
> +            sw.GetStringBuilder().Length = 0;
> +            doc.Save(sw);
> +            xmlDTWriteSchema = sw.ToString();
> +            
> +            StandardizeXmlFormat(ref xmlDSWriteSchema);
> +            
> +            Assert.AreEqual(xmlDSNone, xmlDTNone, "Test#03");
> +            Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGram, "Test#04");
> +            Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchema, "Test#05");
> +                               
> +            // Now that we've tested writing tables (including children),
> +            // we will go on to test the cases where the hierarchy flag
> +            // is false.  For this, we will test one table inside the
> +            // dataset and one table outside the dataset.
> +            
> +            // First, we fix our test DataSet to only have a single table
> +            // with no relations.  Then, we go about comparing the XML.
> +            // Get XML for DataSet writes.
> +            ds.Tables[1].Constraints.Remove(ds.Tables[1].Constraints[0]);
> +            ds.Tables[0].Constraints.Remove(ds.Tables[0].Constraints[0]);
> +            ds.Tables[0].ChildRelations.Remove("MainToChild");
> +            ds.Tables.Remove("Child");
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw);
> +            xmlDSNone = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw, XmlWriteMode.DiffGram);
> +            xmlDSDiffGram = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            ds.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            xmlDSWriteSchema = sw.ToString();
> +            
> +            // Get all the DataTable.WriteXml results.
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw);
> +            string xmlDTNoneInDS = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram);
> +            string xmlDTDiffGramInDS = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            string xmlDTWriteSchemaInDS = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMain.WriteXml(sw);
> +            string xmlDTNoneNoDS = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMain.WriteXml(sw, XmlWriteMode.DiffGram);
> +            string xmlDTDiffGramNoDS = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            string xmlDTWriteSchemaNoDS = sw.ToString();
> +            
> +            Assert.AreEqual(xmlDSNone, xmlDTNoneInDS, "Test#06");
> +
> +            // The only difference between the xml output from inside the
> +            // dataset and the xml output from outside the dataset is that
> +            // there's a fake <DocumentElement> tag surrounding tbe table
> +            // in the second case.  We replace it with the name of the
> +            // dataset for testing purposes.
> +            doc.LoadXml(xmlDTNoneNoDS);
> +            Assert.AreEqual("DocumentElement", doc.DocumentElement.Name, "Test#07");
> +            sw.GetStringBuilder().Length = 0;
> +            doc.Save(sw);
> +            xmlDTNoneNoDS = sw.ToString();
> +            xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("<DocumentElement>", "<MyDataSet>");
> +            xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("</DocumentElement>", "</MyDataSet>");
> +            
> +            StandardizeXmlFormat(ref xmlDSNone);
> +            
> +            Assert.AreEqual(xmlDSNone, xmlDTNoneNoDS, "Test#08");
> +            
> +            // Now check the DiffGram.
> +            Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramInDS, "Test#09");
> +            
> +            doc.LoadXml(xmlDTDiffGramNoDS);
> +            Assert.AreEqual("DocumentElement", doc.DocumentElement.FirstChild.Name, "Test#10");
> +            xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("<DocumentElement>", "<MyDataSet>");
> +            xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("</DocumentElement>", "</MyDataSet>");
> +
> +            Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramNoDS, "Test#11");
> +            
> +            // Finally we check the WriteSchema version of the data.  First
> +            // we remove the extra "msdata:MainDataTable" attribute from
> +            // the schema declaration part of the DataTable xml.
> +            doc = new XmlDocument();
> +            doc.LoadXml(xmlDTWriteSchemaInDS);
> +            node = doc.DocumentElement.FirstChild.FirstChild;
> +            a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
> +            Assert.IsNotNull(a, "Test#12");
> +            Assert.AreEqual("Main", a.Value, "Test#13");
> +            node.Attributes.Remove(a);
> +            sw.GetStringBuilder().Length = 0;
> +            doc.Save(sw);
> +            xmlDTWriteSchemaInDS = sw.ToString();
> +            
> +            StandardizeXmlFormat(ref xmlDSWriteSchema);
> +
> +            Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaInDS, "Test#14");
> +            
> +            // Remove the extra "msdata:MainDataTable" for the other test case.
> +            // Also make sure we have "NewDataSet" in the appropriate locations.
> +            doc = new XmlDocument();
> +            doc.LoadXml(xmlDTWriteSchemaNoDS);
> +            node = doc.DocumentElement.FirstChild.FirstChild;
> +            a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
> +            Assert.IsNotNull(a, "Test#15");
> +            Assert.AreEqual("Main", a.Value, "Test#16");
> +            node.Attributes.Remove(a);
> +            sw.GetStringBuilder().Length = 0;
> +            doc.Save(sw);
> +            
> +            Assert.AreEqual("NewDataSet", doc.DocumentElement.Name, "Test#17");
> +            Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.Attributes["id"].Value, "Test#18");
> +            Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.FirstChild.Attributes["name"].Value, "Test#19");
> +            
> +            xmlDTWriteSchemaNoDS = sw.ToString();
> +            
> +            xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("<NewDataSet>","<MyDataSet>");
> +            xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("</NewDataSet>","</MyDataSet>");
> +            xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("\"NewDataSet\"","\"MyDataSet\"");
> +
> +            Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaNoDS, "Test#20");
> +        }
> +        
> +        [Test]
> +        public void TestReadXml()
> +        {
> +            // For reading, DataTable.ReadXml only supports reading in xml with
> +            // the schema included.  This means that we can only read in XML
> +            // that was generated with the WriteSchema flag.  
> +            DataSet ds;
> +            DataTable dtMainInDS, dtChildInDS, dtMain;
> +            
> +            GenerateTestData(out ds,
> +                             out dtMainInDS,
> +                             out dtChildInDS,
> +                             out dtMain);
> +            
> +            StringWriter sw = new StringWriter();
> +            
> +            // Get XML for recursive DataTable writes of the same data as in
> +            // the DataSet.
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, true);
> +            string xmlDTNone = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
> +            string xmlDTDiffGram = sw.ToString();
> +
> +            sw.GetStringBuilder().Length = 0;
> +            dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
> +            string xmlMultiTable = sw.ToString();
> +            
> +            sw.GetStringBuilder().Length = 0;
> +            dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            string xmlSingleTable = sw.ToString();
> +            
> +            DataTable newdt = new DataTable();
> +
> +            try {
> +                newdt.ReadXml(new StringReader(xmlDTNone));
> +                Assert.Fail("Test#01");
> +            } catch(InvalidOperationException) {
> +                // DataTable does not support schema inference from Xml.
> +            }
> +            
> +            try {
> +                newdt.ReadXml(new StringReader(xmlDTDiffGram));
> +                Assert.Fail("Test#02");
> +            } catch(InvalidOperationException) {
> +                // DataTable does not support schema inference from Xml.
> +            }
> +            
> +            DataTable multiTable = new DataTable();
> +            multiTable.ReadXml(new StringReader(xmlMultiTable));
> +            // Do some simple checks to see if the main dataset was created
> +            // and if there are relationships present.
> +            Assert.AreEqual("MyDataSet", multiTable.DataSet.DataSetName, "Test#03");
> +            Assert.AreEqual(1, multiTable.ChildRelations.Count, "Test#04");
> +            Assert.AreEqual(1, multiTable.Constraints.Count, "Test#05");
> +            // Write the table back out and check to see that the XML is
> +            // the same as before.
> +            sw.GetStringBuilder().Length = 0;
> +            multiTable.WriteXml(sw, XmlWriteMode.WriteSchema, true);
> +            string xmlMultiTableCheck = sw.ToString();
> +            Assert.AreEqual(xmlMultiTable, xmlMultiTableCheck, "Test#06");
> +            
> +            DataTable singleTable = new DataTable();
> +            singleTable.ReadXml(new StringReader(xmlSingleTable));
> +            // Do some simple checks on the table.
> +            Assert.IsNull(singleTable.DataSet, "Test#07");
> +            Assert.AreEqual("Main", singleTable.TableName, "Test#08");
> +            // Write the table out and check if it's the same.
> +            sw.GetStringBuilder().Length = 0;
> +            singleTable.WriteXml(sw, XmlWriteMode.WriteSchema);
> +            string xmlSingleTableCheck = sw.ToString();
> +            Assert.AreEqual(xmlSingleTable, xmlSingleTableCheck, "Test#09");
> +        }
> +    }
> +}
> +#endif
> Index: System.Data.dll.sources
> ===================================================================
> --- System.Data.dll.sources	(revision 66162)
> +++ System.Data.dll.sources	(working copy)
> @@ -318,6 +318,7 @@
>  System.Data/XmlDataLoader.cs
>  System.Data/XmlSchemaDataImporter.cs
>  System.Data/XmlSchemaWriter.cs
> +System.Data/XmlTableWriter.cs
>  System.Xml/XmlDataDocument.cs
>  Mono.Data.SqlExpressions/Tokenizer.cs
>  Mono.Data.SqlExpressions/Numeric.cs
> Index: System.Data_test.dll.sources
> ===================================================================
> --- System.Data_test.dll.sources	(revision 66162)
> +++ System.Data_test.dll.sources	(working copy)
> @@ -40,6 +40,7 @@
>  System.Data/DataTableTest2.cs
>  System.Data/DataTableLoadRowTest.cs
>  System.Data/DataTableReaderTest.cs
> +System.Data/DataTableReadWriteXmlTest.cs
>  System.Data/DataViewManagerTest.cs
>  System.Data/DataViewTest.cs
>  System.Data/DataViewTest2.cs
> Index: ChangeLog
> ===================================================================
> --- ChangeLog	(revision 66162)
> +++ ChangeLog	(working copy)
> @@ -1,3 +1,7 @@
> +2006-10-02	Patrick Earl <mono at patearl.net>
> +
> +	* Implemented DataTable.WriteXml
> +
>  2006-09-26	Boris Kirzner <borisk at mainsoft.com>
>  
>  	* run-tests.test.disconnected.bat,run-tests.test.connected.bat: 
> Index: System.Data/XmlSchemaWriter.cs
> ===================================================================
> --- System.Data/XmlSchemaWriter.cs	(revision 66162)
> +++ System.Data/XmlSchemaWriter.cs	(working copy)
> @@ -64,16 +64,50 @@
>  			XmlWriter writer, DataTableCollection tables,
>  			DataRelationCollection relations)
>  		{
> -			ds = dataset;
> +			dataSetName = dataset.DataSetName;
> +			dataSetNamespace = dataset.Namespace;
> +			dataSetLocale = dataset.Locale;
> +			dataSetProperties = dataset.ExtendedProperties;
>  			w = writer;
> +			if (tables != null) {
> +				this.tables = new DataTable[tables.Count];
> +				for(int i=0;i<tables.Count;i++) this.tables[i] = tables[i];
> +			}
> +			if (relations != null) {
> +				this.relations = new DataRelation[relations.Count];
> +				for(int i=0;i<relations.Count;i++) this.relations[i] = relations[i];
> +			}
> +		}
> +
> +		public XmlSchemaWriter (XmlWriter writer,
> +			DataTable[] tables,
> +			DataRelation[] relations,
> +			string mainDataTable,
> +			string dataSetName)
> +		{
> +			w = writer;
>  			this.tables = tables;
>  			this.relations = relations;
> +			this.mainDataTable = mainDataTable;
> +			this.dataSetName = dataSetName;
> +			this.dataSetProperties = new PropertyCollection();
> +			if (tables[0].DataSet != null) {
> +				dataSetNamespace = tables[0].DataSet.Namespace;
> +				dataSetLocale = tables[0].DataSet.Locale;
> +			} else {
> +				dataSetNamespace = tables[0].Namespace;
> +				dataSetLocale = tables[0].Locale;
> +			}
>  		}
>  
> -		DataSet ds;
>  		XmlWriter w;
> -		DataTableCollection tables;
> -		DataRelationCollection relations;
> +		DataTable[] tables;
> +		DataRelation[] relations;
> +		string mainDataTable;
> +		string dataSetName;
> +		string dataSetNamespace;
> +		PropertyCollection dataSetProperties;
> +		CultureInfo dataSetLocale;
>  
>  		ArrayList globalTypeTables = new ArrayList ();
>  		Hashtable additionalNamespaces = new Hashtable ();
> @@ -81,7 +115,7 @@
>  		ArrayList annotation = new ArrayList ();
>  
>  		public string ConstraintPrefix {
> -			get { return ds.Namespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
> +			get { return dataSetNamespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
>  		}
>  
>  		// the whole DataSet
> @@ -99,18 +133,18 @@
>  			}
>  
>  			w.WriteStartElement ("xs", "schema", xmlnsxs);
> -			w.WriteAttributeString ("id", XmlHelper.Encode (ds.DataSetName));
> +			w.WriteAttributeString ("id", XmlHelper.Encode (dataSetName));
>  
> -			if (ds.Namespace != String.Empty) {
> +			if (dataSetNamespace != String.Empty) {
>  				w.WriteAttributeString ("targetNamespace",
> -					ds.Namespace);
> +					dataSetNamespace);
>  				w.WriteAttributeString (
>  					"xmlns",
>  					XmlConstants.TnsPrefix,
>  					XmlConstants.XmlnsNS,
> -					ds.Namespace);
> +					dataSetNamespace);
>  			}
> -			w.WriteAttributeString ("xmlns", ds.Namespace);
> +			w.WriteAttributeString ("xmlns", dataSetNamespace);
>  
>  			w.WriteAttributeString ("xmlns", "xs",
>  				XmlConstants.XmlnsNS, xmlnsxs);
> @@ -125,7 +159,7 @@
>  					XmlConstants.XmlnsNS,
>  					XmlConstants.MspropNamespace);
>  
> -			if (ds.Namespace != String.Empty) {
> +			if (dataSetNamespace != String.Empty) {
>  				w.WriteAttributeString ("attributeFormDefault", "qualified");
>  				w.WriteAttributeString ("elementFormDefault", "qualified");
>  			}
> @@ -156,12 +190,19 @@
>  		private void WriteDataSetElement ()
>  		{
>  			w.WriteStartElement ("xs", "element", xmlnsxs);
> -			w.WriteAttributeString ("name", XmlHelper.Encode (ds.DataSetName));
> +			w.WriteAttributeString ("name", XmlHelper.Encode (dataSetName));
>  			w.WriteAttributeString (XmlConstants.MsdataPrefix,
>  				"IsDataSet", XmlConstants.MsdataNamespace,
>  				"true");
> +
> +			if(mainDataTable != null && mainDataTable != "")
> +				w.WriteAttributeString (
> +					XmlConstants.MsdataPrefix,
> +					"MainDataTable",
> +					XmlConstants.MsdataNamespace,
> +					mainDataTable);
>  #if NET_2_0
> -			if (ds.Locale == CultureInfo.CurrentCulture) {
> +			if (dataSetLocale == CultureInfo.CurrentCulture) {
>  				w.WriteAttributeString (
>  					XmlConstants.MsdataPrefix,
>  					"UseCurrentCulture",
> @@ -175,10 +216,10 @@
>  					XmlConstants.MsdataPrefix,
>  					"Locale",
>  					XmlConstants.MsdataNamespace,
> -					ds.Locale.Name);
> +					dataSetLocale.Name);
>  			}
>  
> -			AddExtendedPropertyAttributes (ds.ExtendedProperties);
> +			AddExtendedPropertyAttributes (dataSetProperties);
>  
>  			w.WriteStartElement ("xs", "complexType", xmlnsxs);
>  			w.WriteStartElement ("xs", "choice", xmlnsxs);
> @@ -194,7 +235,7 @@
>  				}
>  				
>  				if (isTopLevel) {
> -					if (ds.Namespace != table.Namespace) {
> +					if (dataSetNamespace != table.Namespace) {
>  						// <xs:element ref="X:y" />
>  						w.WriteStartElement ("xs",
>  							"element",
> @@ -286,7 +327,12 @@
>  					}
>  
>  					ForeignKeyConstraint fk = c as ForeignKeyConstraint;
> -					if (fk != null && (relations == null || !(relations.Contains (fk.ConstraintName)))) {
> +					bool haveConstraint = false;
> +					if (relations != null)
> +						foreach (DataRelation r in relations)
> +							if(r.RelationName == fk.ConstraintName)
> +								haveConstraint = true;
> +					if (fk != null && !haveConstraint) {
>  						DataRelation rel = new DataRelation (fk.ConstraintName,
>  										fk.RelatedColumns, fk.Columns);
>  						AddForeignKeys (rel, names, true);
> @@ -399,12 +445,12 @@
>  			// first try to find the concatenated name. If we didn't find it - use constraint name.
>  			if (names.Contains (concatName)) {
>  				w.WriteStartAttribute ("refer", String.Empty);
> -				w.WriteQualifiedName (concatName, ds.Namespace);
> +				w.WriteQualifiedName (concatName, dataSetNamespace);
>  				w.WriteEndAttribute ();
>  			}
>  			else {
>  				w.WriteStartAttribute ("refer", String.Empty);
> -				w.WriteQualifiedName (XmlHelper.Encode (uqConst.ConstraintName), ds.Namespace);
> +				w.WriteQualifiedName (XmlHelper.Encode (uqConst.ConstraintName), dataSetNamespace);
>  				w.WriteEndAttribute ();
>  			}
>  
> @@ -445,10 +491,10 @@
>  		// ExtendedProperties
>  
>  		private bool CheckExtendedPropertyExists (
> -			DataTableCollection tables,
> -			DataRelationCollection relations)
> +			DataTable[] tables,
> +			DataRelation[] relations)
>  		{
> -			if (ds.ExtendedProperties.Count > 0)
> +			if (dataSetProperties.Count > 0)
>  				return true;
>  			foreach (DataTable dt in tables) {
>  				if (dt.ExtendedProperties.Count > 0)
> @@ -640,7 +686,7 @@
>  
>  		private void WriteChildRelations (DataRelation rel)
>  		{
> -			if (rel.ChildTable.Namespace != ds.Namespace) {
> +			if (rel.ChildTable.Namespace != dataSetNamespace) {
>  				w.WriteStartElement ("xs", "element", xmlnsxs);
>  				w.WriteStartAttribute ("ref", String.Empty);
>  				w.WriteQualifiedName (
> @@ -734,8 +780,8 @@
>  		{
>  			if (ns == String.Empty)
>  				return;
> -			if (ds.Namespace != ns) {
> -				if (names [prefix] != ns) {
> +			if (dataSetNamespace != ns) {
> +				if ((string)names [prefix] != ns) {
>  					for (int i = 1; i < int.MaxValue; i++) {
>  						string p = "app" + i;
>  						if (names [p] == null) {
> Index: System.Data/DataSet.cs
> ===================================================================
> --- System.Data/DataSet.cs	(revision 66162)
> +++ System.Data/DataSet.cs	(working copy)
> @@ -1538,29 +1538,33 @@
>  				WriteTable ( writer, table, mode, version);
>  		}
>  
> -		private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
> +		internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
>  		{
>  			DataRow[] rows = table.NewRowArray(table.Rows.Count);
>  			table.Rows.CopyTo (rows, 0);
>  			WriteTable (writer, rows, mode, version, true);
>  		}
>  
> -		private void WriteTable (XmlWriter writer,
> +		internal static void WriteTable (XmlWriter writer,
>  			DataRow [] rows,
>  			XmlWriteMode mode,
>  			DataRowVersion version, bool skipIfNested)
>  		{
> +			if (rows.Length == 0) return;
> +			DataTable table = rows[0].Table;
> +
> +			if (table.TableName == null || table.TableName == "")
> +				throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");
> +
>  			//The columns can be attributes, hidden, elements, or simple content
>  			//There can be 0-1 simple content cols or 0-* elements
>  			System.Collections.ArrayList atts;
>  			System.Collections.ArrayList elements;
>  			DataColumn simple = null;
>  
> -			if (rows.Length == 0) return;
> -			DataTable table = rows[0].Table;
>  			SplitColumns (table, out atts, out elements, out simple);
>  			//sort out the namespacing
> -			string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
> +			string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;
>  			int relationCount = table.ParentRelations.Count;
>  			DataRelation oneRel = relationCount == 1 ? table.ParentRelations [0] : null;
>  
> @@ -1628,7 +1632,7 @@
>  
>  		}
>  
> -		private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
> +		internal static void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
>  		{
>  			string colnspc = null;
>  			object rowObject = row [col, version];
> @@ -1645,16 +1649,16 @@
>  			writer.WriteEndElement ();
>  		}
>  
> -		private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
> +		internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
>  		{
>  			if (!row.IsNull (col))
>  				WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));
>  		}
>  
> -		private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
> +		internal static 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;
> +			string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;
>  
>  			WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));
>  
> @@ -1672,12 +1676,12 @@
>  			}
>  		}
>  		    
> -		private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
> +		internal static 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)
> +		internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
>  		{
>  			switch ( mode) {
>  				case XmlWriteMode.WriteSchema:
> @@ -1695,7 +1699,7 @@
>  		internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
>  		{
>  			if (mode == XmlWriteMode.DiffGram) {
> -				SetTableRowsID (table);
> +				table.SetRowsID();
>  				WriteDiffGramElement (writer);
>  			}
>  			
> @@ -1760,7 +1764,7 @@
>  			}
>  		}
>  
> -		private void WriteDiffGramElement(XmlWriter writer)
> +		internal static void WriteDiffGramElement(XmlWriter writer)
>  		{
>  			WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
>  			WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
> @@ -1768,18 +1772,9 @@
>  
>  		private void SetRowsID()
>  		{
> -			foreach (DataTable Table in Tables)
> -				SetTableRowsID (Table);
> +			foreach (DataTable table in Tables)
> +				table.SetRowsID();
>  		}
> -		
> -		private void SetTableRowsID (DataTable Table)
> -		{
> -			int dataRowID = 0;
> -			foreach (DataRow Row in Table.Rows) {
> -				Row.XmlRowID = dataRowID;
> -				dataRowID++;
> -			}
> -		}
>  		#endregion //Private Xml Serialisation
>  	}
>  }
> Index: System.Data/XmlTableWriter.cs
> ===================================================================
> --- System.Data/XmlTableWriter.cs	(revision 0)
> +++ System.Data/XmlTableWriter.cs	(revision 0)
> @@ -0,0 +1,97 @@
> +// 
> +// System.Data/XmlTableWriter.cs
> +//
> +// Author:
> +//   Patrick Earl <mono at patearl.net>
> +//
> +// Copyright (c) 2006, Patrick Earl
> +//
> +// 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.
> +
> +#if NET_2_0
> +using System;
> +using System.Collections.Generic;
> +using System.Data;
> +using System.Xml;
> +
> +internal class XmlTableWriter {
> +	// This method is modelled after the DataSet's WriteXml functionality.
> +	internal static void WriteTables(XmlWriter writer,
> +		                 XmlWriteMode mode,
> +				 List<DataTable> tables,
> +				 List<DataRelation> relations,
> +				 string mainDataTable,
> +				 string dataSetName)
> +	{
> +		if (mode == XmlWriteMode.DiffGram) {
> +			foreach (DataTable table in tables)
> +				table.SetRowsID();
> +			DataSet.WriteDiffGramElement(writer);
> +		}
> +
> +		bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
> +		for (int n = 0; n < tables.Count && !shouldOutputContent; n++)
> +			shouldOutputContent = tables[n].Rows.Count > 0;
> +
> +		if (shouldOutputContent) {
> +			// We assume that tables[0] is the main table being written.
> +			// We happen to know that the code above us does things that way.
> +			DataSet.WriteStartElement(writer, mode, tables[0].Namespace, tables[0].Prefix, XmlHelper.Encode(dataSetName));
> +
> +			if (mode == XmlWriteMode.WriteSchema) {
> +				new XmlSchemaWriter(writer,
> +					tables.ToArray(),
> +					relations.ToArray(),
> +					mainDataTable,
> +					dataSetName
> +				).WriteSchema();
> +			}
> +
> +			WriteTableList (writer, mode, tables, DataRowVersion.Default);
> +
> +			writer.WriteEndElement();
> +		}
> +
> +		if (mode == XmlWriteMode.DiffGram) {
> +			List<DataTable> changedTables = new List<DataTable>();
> +			foreach (DataTable table in tables) {
> +				DataTable changed = table.GetChanges(DataRowState.Modified | DataRowState.Deleted);
> +				if (changed != null && changed.Rows.Count > 0)
> +					changedTables.Add(changed);
> +			}
> +			if (changedTables.Count > 0) {
> +				DataSet.WriteStartElement(writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
> +				WriteTableList (writer, mode, changedTables, DataRowVersion.Original);
> +				writer.WriteEndElement();
> +			}
> +		
> +			writer.WriteEndElement(); // diffgr:diffgram
> +		}
> +
> +		writer.Flush();
> +	}
> +
> +	internal static void WriteTableList(XmlWriter writer, XmlWriteMode mode, List<DataTable> tables, DataRowVersion version)
> +	{
> +		foreach (DataTable table in tables)
> +			DataSet.WriteTable(writer, table, mode, version);
> +	}
> +}
> +#endif
> Index: System.Data/DataTable.cs
> ===================================================================
> --- System.Data/DataTable.cs	(revision 66162)
> +++ System.Data/DataTable.cs	(working copy)
> @@ -43,6 +43,9 @@
>  using System;
>  using System.Data.Common;
>  using System.Collections;
> +#if NET_2_0
> +using System.Collections.Generic;
> +#endif
>  using System.ComponentModel;
>  using System.Globalization;
>  using System.IO;
> @@ -1929,10 +1932,49 @@
>  		}
>  
>  #if NET_2_0
> +		public XmlReadMode ReadXml (Stream stream)
> +		{
> +			return ReadXml (new XmlTextReader(stream, null));
> +		}
> +
> +		public XmlReadMode ReadXml (string fileName)
> +		{
> +			XmlReader reader = new XmlTextReader(fileName);
> +			try {
> +				return ReadXml (reader);
> +			} finally {
> +				reader.Close();
> +			}
> +		}
> +
> +		public XmlReadMode ReadXml (TextReader reader)
> +		{
> +			return ReadXml (new XmlTextReader(reader));
> +		}
> +
>  		[MonoTODO]
> -		XmlReadMode ReadXml (Stream stream)
> +		public XmlReadMode ReadXml (XmlReader reader)
>  		{
> -			throw new NotImplementedException ();
> +			// The documentation from MS for this method is rather
> +			// poor.  The following cases have been observed
> +			// during testing:
> +			//
> +			//     Reading a table from XML may create a DataSet to
> +			//     store child tables.
> +			//
> +			//     If the table has at least one column present,
> +			//     we do not require the schema to be present in
> +			//     the xml.  If the table has no columns, neither
> +			//     regular data nor diffgrams will be read, but
> +			//     will throw an error indicating that schema
> +			//     will not be inferred.
> +			//
> +			//     We will likely need to take advantage of the
> +			//     msdata:MainDataTable attribute added to the
> +			//     schema info to load into the appropriate
> +			//     locations.
> +
> +			throw new NotImplementedException();
>  		}
>  
>  		public void ReadXmlSchema (Stream stream)
> @@ -2244,57 +2286,158 @@
>  		{
>  			XmlWriterSettings s = new XmlWriterSettings ();
>  			s.Indent = true;
> +			s.OmitXmlDeclaration = true;
>  			return s;
>  		}
>  
>  		public void WriteXml (Stream stream)
>  		{
> -			WriteXml (stream, XmlWriteMode.IgnoreSchema);
> +			WriteXml (stream, XmlWriteMode.IgnoreSchema, false);
>  		}
>  
> +		public void WriteXml (string fileName)
> +		{
> +			WriteXml (fileName, XmlWriteMode.IgnoreSchema, false);
> +		}
> +
>  		public void WriteXml (TextWriter writer)
>  		{
> -			WriteXml (writer, XmlWriteMode.IgnoreSchema);
> +			WriteXml (writer, XmlWriteMode.IgnoreSchema, false);
>  		}
>  
>  		public void WriteXml (XmlWriter writer)
>  		{
> -			WriteXml (writer, XmlWriteMode.IgnoreSchema);
> +			WriteXml (writer, XmlWriteMode.IgnoreSchema, false);
>  		}
>  
> -		public void WriteXml (string fileName)
> +		public void WriteXml (Stream stream, XmlWriteMode mode)
>  		{
> -			WriteXml (fileName, XmlWriteMode.IgnoreSchema);
> +			WriteXml (stream, mode, false);
>  		}
>  
> -		public void WriteXml (Stream stream, XmlWriteMode mode)
> +		public void WriteXml (string fileName, XmlWriteMode mode)
>  		{
> -			WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode);
> +			WriteXml (fileName, mode, false);
>  		}
>  
>  		public void WriteXml (TextWriter writer, XmlWriteMode mode)
>  		{
> -			WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode);
> +			WriteXml (writer, mode, false);
>  		}
>  
> -		[MonoTODO]
>  		public void WriteXml (XmlWriter writer, XmlWriteMode mode)
>  		{
> -			throw new NotImplementedException ();
> +			WriteXml (writer, mode, false);
>  		}
>  
> -		public void WriteXml (string fileName, XmlWriteMode mode)
> +		public void WriteXml (Stream stream, bool writeHierarchy)
>  		{
> +			WriteXml (stream, XmlWriteMode.IgnoreSchema, writeHierarchy);
> +		}
> +
> +		public void WriteXml (string fileName, bool writeHierarchy)
> +		{
> +			WriteXml (fileName, XmlWriteMode.IgnoreSchema, writeHierarchy);
> +		}
> +
> +		public void WriteXml (TextWriter writer, bool writeHierarchy)
> +		{
> +			WriteXml (writer, XmlWriteMode.IgnoreSchema, writeHierarchy);
> +		}
> +
> +		public void WriteXml (XmlWriter writer, bool writeHierarchy)
> +		{
> +			WriteXml (writer, XmlWriteMode.IgnoreSchema, writeHierarchy);
> +		}
> +
> +		public void WriteXml (Stream stream, XmlWriteMode mode, bool writeHierarchy)
> +		{
> +			WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode, writeHierarchy);
> +		}
> +
> +		public void WriteXml (string fileName, XmlWriteMode mode, bool writeHierarchy)
> +		{
>  			XmlWriter xw = null;
>  			try {
>  				xw = XmlWriter.Create (fileName, GetWriterSettings ());
> -				WriteXml (xw, mode);
> +				WriteXml (xw, mode, writeHierarchy);
>  			} finally {
>  				if (xw != null)
>  					xw.Close ();
>  			}
>  		}
>  
> +		public void WriteXml (TextWriter writer, XmlWriteMode mode, bool writeHierarchy)
> +		{
> +			WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode, writeHierarchy);
> +		}
> +
> +		public void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writeHierarchy)
> +		{
> +			// If we're in mode XmlWriteMode.WriteSchema, we need to output an extra
> +			// msdata:MainDataTable attribute that wouldn't normally be part of the
> +			// DataSet WriteXml output.
> +			//
> +			// For the writeHierarchy == true case, we write what would be output by
> +			// a DataSet write, but we limit ourselves to our table and its descendants.
> +			//
> +			// For the writeHierarchy == false case, we write what would be output by
> +			// a DataSet write, but we limit ourselves to this table.
> +			//
> +			// If the table is not in a DataSet, we follow the following behaviour:
> +			//   For WriteSchema cases, we do a write as if there is a wrapper
> +			//   dataset called NewDataSet.
> +			//   For IgnoreSchema or DiffGram cases, we do a write as if there
> +			//   is a wrapper dataset called DocumentElement.
> +			
> +			// Generate a list of tables to write.
> +			List<DataTable> tables = new List<DataTable>();	
> +			if (writeHierarchy == false)
> +				tables.Add(this);
> +			else
> +				FindAllChildren(tables, this);
> +
> +			// If we're in a DataSet, generate a list of relations to write.
> +			List<DataRelation> relations = new List<DataRelation>();
> +			if (DataSet != null)
> +			{
> +				foreach(DataRelation relation in DataSet.Relations)
> +				{
> +					if(tables.Contains(relation.ParentTable) &&
> +					   tables.Contains(relation.ChildTable))
> +						relations.Add(relation);
> +				}
> +			}
> +
> +			// Add the msdata:MainDataTable info if we're writing schema data.
> +			string mainDataTable = null;
> +			if (mode == XmlWriteMode.WriteSchema)
> +				mainDataTable = this.TableName;
> +
> +			// Figure out the DataSet name.
> +			string dataSetName = null;
> +			if (DataSet != null)
> +				dataSetName = DataSet.DataSetName;
> +			else if (DataSet == null && mode == XmlWriteMode.WriteSchema)
> +				dataSetName = "NewDataSet";
> +			else
> +				dataSetName = "DocumentElement";
> +				
> +			XmlTableWriter.WriteTables(writer, mode, tables, relations, mainDataTable, dataSetName);
> +		}
> +
> +		private void FindAllChildren(List<DataTable> list, DataTable root)
> +		{
> +			if (!list.Contains(root))
> +			{
> +				list.Add(root);
> +				foreach (DataRelation relation in root.ChildRelations)
> +				{
> +					FindAllChildren(list, relation.ChildTable);
> +				}
> +			}
> +		}
> +
>  		public void WriteXmlSchema (Stream stream)
>  		{
>  			WriteXmlSchema (XmlWriter.Create (stream, GetWriterSettings ()));
> @@ -2581,5 +2724,14 @@
>  		internal void ResetPropertyDescriptorsCache() {
>  			_propertyDescriptorsCache = null;
>  		}
> +
> +		internal void SetRowsID()
> +		{
> +			int dataRowID = 0;
> +			foreach (DataRow row in Rows) {
> +				row.XmlRowID = dataRowID;
> +				dataRowID++;
> +			}
> +		}
>  	}
>  }
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>   

-- 
Nagappan A <anagappan at novell.com>
Novell Software Development (I) Pvt. Ltd.
Linux Desktop Testing Project - http://ldtp.freedesktop.org
http://nagappanal.blogspot.com/

Novell, Inc.
SUSE® Linux Enterprise 10
Your Linux is ready™
http://www.novell.com/linux




More information about the Mono-devel-list mailing list