Fix method access modifier.
[mono.git] / mcs / class / System.Data / System.Data / DataSet.cs
1 // 
2 // System.Data/DataSet.cs
3 //
4 // Author:
5 //   Christopher Podurgiel <cpodurgiel@msn.com>
6 //   Daniel Morgan <danmorg@sc.rr.com>
7 //   Rodrigo Moya <rodrigo@ximian.com>
8 //   Stuart Caborn <stuart.caborn@virgin.net>
9 //   Tim Coleman (tim@timcoleman.com)
10 //   Ville Palo <vi64pa@koti.soon.fi>
11 //
12 // (C) Ximian, Inc. 2002
13 // Copyright (C) Tim Coleman, 2002, 2003
14 //
15
16 using System;
17 using System.Collections;
18 using System.ComponentModel;
19 using System.Globalization;
20 using System.Threading;
21 using System.IO;
22 using System.Runtime.Serialization;
23 using System.Xml;
24 using System.Xml.Schema;
25 using System.Xml.Serialization;
26 using System.Data.Common;
27
28 namespace System.Data {
29
30         [ToolboxItem (false)]
31         [DefaultProperty ("DataSetName")]
32         [Serializable]
33         public class DataSet : MarshalByValueComponent, IListSource, 
34                 ISupportInitialize, ISerializable, IXmlSerializable 
35         {
36                 private string dataSetName;
37                 private string _namespace = "";
38                 private string prefix;
39                 private bool caseSensitive;
40                 private bool enforceConstraints = true;
41                 private DataTableCollection tableCollection;
42                 private DataRelationCollection relationCollection;
43                 private PropertyCollection properties;
44                 private DataViewManager defaultView;
45                 private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
46                 
47                 #region Constructors
48
49                 public DataSet () : this ("NewDataSet") 
50                 {               
51                 }
52                 
53                 public DataSet (string name)
54                 {
55                         dataSetName = name;
56                         tableCollection = new DataTableCollection (this);
57                         relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
58                         properties = new PropertyCollection ();
59                         this.prefix = String.Empty;
60                         
61                         this.Locale = CultureInfo.CurrentCulture;
62                 }
63
64                 [MonoTODO]
65                 protected DataSet (SerializationInfo info, StreamingContext context) : this ()
66                 {
67                         throw new NotImplementedException ();
68                 }
69
70                 #endregion // Constructors
71
72                 #region Public Properties
73
74                 [DataCategory ("Data")]
75                 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
76                 [DefaultValue (false)]
77                 public bool CaseSensitive {
78                         get {
79                                 return caseSensitive;
80                         } 
81                         set {
82                                 foreach (DataTable T in Tables) {
83                                         if (T.VirginCaseSensitive)
84                                                 T.CaseSensitive = value;
85                                 }
86
87                                 caseSensitive = value; 
88                                 if (!caseSensitive) {
89                                         foreach (DataTable table in Tables) {
90                                                 foreach (Constraint c in table.Constraints)
91                                                         c.AssertConstraint ();
92                                         }
93                                 }
94                         }
95                 }
96
97                 [DataCategory ("Data")]
98                 [DataSysDescription ("The name of this DataSet.")]
99                 [DefaultValue ("")]
100                 public string DataSetName {
101                         get { return dataSetName; } 
102                         set { dataSetName = value; }
103                 }
104
105                 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
106                 [Browsable (false)]
107                 public DataViewManager DefaultViewManager {
108                         get {
109                                 if (defaultView == null)
110                                         defaultView = new DataViewManager (this);
111                                 return defaultView;
112                         } 
113                 }
114
115                 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
116                 [DefaultValue (true)]
117                 public bool EnforceConstraints {
118                         get { return enforceConstraints; } 
119                         set { 
120                                 if (value != enforceConstraints) {
121                                         enforceConstraints = value; 
122                                         if (value) {
123                                                 foreach (DataTable table in Tables) {
124                                                         foreach (Constraint c in table.Constraints)
125                                                                 c.AssertConstraint ();
126                                                 }
127                                         }
128                                 }
129                         }
130                 }
131
132                 [Browsable (false)]
133                 [DataCategory ("Data")]
134                 [DataSysDescription ("The collection that holds custom user information.")]
135                 public PropertyCollection ExtendedProperties {
136                         get { return properties; }
137                 }
138
139                 [Browsable (false)]
140                 [DataSysDescription ("Indicates that the DataSet has errors.")]
141                 public bool HasErrors {
142                         [MonoTODO]
143                         get {
144                                 for (int i = 0; i < Tables.Count; i++) {
145                                         if (Tables[i].HasErrors)
146                                                 return true;
147                                 }
148                                 return false;
149                         }
150                 }
151
152                 [DataCategory ("Data")]
153                 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
154                 public CultureInfo Locale {
155                         get {
156                                 return locale;
157                         }
158                         set {
159                                 if (locale == null || !locale.Equals (value)) {
160                                         // TODO: check if the new locale is valid
161                                         // TODO: update locale of all tables
162                                         locale = value;
163                                 }
164                         }
165                 }
166
167                 public void Merge (DataRow[] rows)
168                 {
169                         Merge (rows, false, MissingSchemaAction.Add);
170                 }
171                 
172                 public void Merge (DataSet dataSet)
173                 {
174                         Merge (dataSet, false, MissingSchemaAction.Add);
175                 }
176                 
177                 public void Merge (DataTable table)
178                 {
179                         Merge (table, false, MissingSchemaAction.Add);
180                 }
181                 
182                 public void Merge (DataSet dataSet, bool preserveChanges)
183                 {
184                         Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
185                 }
186                 
187                 [MonoTODO]
188                 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
189                 {
190                         if (rows == null)
191                                 throw new ArgumentNullException ("rows");
192                         if (!IsLegalSchemaAction (missingSchemaAction))
193                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");
194                         
195                         MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
196                 }
197                 
198                 [MonoTODO]
199                 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
200                 {
201                         if (dataSet == null)
202                                 throw new ArgumentNullException ("dataSet");
203                         if (!IsLegalSchemaAction (missingSchemaAction))
204                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");
205                         
206                         MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
207                 }
208                 
209                 [MonoTODO]
210                 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
211                 {
212                         if (table == null)
213                                 throw new ArgumentNullException ("table");
214                         if (!IsLegalSchemaAction (missingSchemaAction))
215                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");
216                         
217                         MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
218                 }
219
220                 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
221                 {
222                         if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
223                                 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
224                                 return true;
225                         return false;
226                 }
227                 
228                 [DataCategory ("Data")]
229                 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
230                 [DefaultValue ("")]
231                 public string Namespace {
232                         [MonoTODO]
233                         get { return _namespace; } 
234                         [MonoTODO]
235                         set {
236                                 //TODO - trigger an event if this happens?
237                                 _namespace = value;
238                         }
239                 }
240
241                 [DataCategory ("Data")]
242                 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
243                 [DefaultValue ("")]
244                 public string Prefix {
245                         [MonoTODO]
246                         get { return prefix; } 
247                         [MonoTODO]
248                         set {
249                                 //TODO - trigger an event if this happens?
250
251                                 if (value == null)
252                                         value = string.Empty;
253                                 
254                                 if (value != this.prefix) 
255                                         RaisePropertyChanging ("Prefix");
256                                 prefix = value;
257                         }
258                 }
259
260                 [DataCategory ("Data")]
261                 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
262                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
263                 public DataRelationCollection Relations {
264                         get {
265                                 return relationCollection;              
266                         }
267                 }
268
269                 [Browsable (false)]
270                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
271                 public override ISite Site {
272                         [MonoTODO]
273                         get {
274                                 throw new NotImplementedException ();
275                         } 
276                         
277                         [MonoTODO]
278                         set {
279                                 throw new NotImplementedException ();
280                         }
281                 }
282
283                 [DataCategory ("Data")]
284                 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
285                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
286                 public DataTableCollection Tables {
287                         get { return tableCollection; }
288                 }
289
290                 #endregion // Public Properties
291
292                 #region Public Methods
293
294                 [MonoTODO]
295                 public void AcceptChanges ()
296                 {
297                         foreach (DataTable tempTable in tableCollection)
298                                 tempTable.AcceptChanges ();
299                 }
300
301                 public void Clear ()
302                 {
303                         // TODO: if currently bound to a XmlDataDocument
304                         //       throw a NotSupportedException
305                         for (int t = 0; t < tableCollection.Count; t++) {
306                                 tableCollection[t].Clear ();
307                         }
308                 }
309
310                 public virtual DataSet Clone ()
311                 {
312                         DataSet Copy = new DataSet ();
313                         CopyProperties (Copy);
314
315                         foreach (DataTable Table in Tables) {
316                                 Copy.Tables.Add (Table.Clone ());
317                         }
318
319                         //Copy Relationships between tables after existance of tables
320                         //and setting properties correctly
321                         CopyRelations (Copy);
322                         
323                         return Copy;
324                 }
325
326                 // Copies both the structure and data for this DataSet.
327                 public DataSet Copy ()
328                 {
329                         DataSet Copy = new DataSet ();
330                         CopyProperties (Copy);
331
332                         // Copy DatSet's tables
333                         foreach (DataTable Table in Tables) 
334                                 Copy.Tables.Add (Table.Copy ());
335
336                         //Copy Relationships between tables after existance of tables
337                         //and setting properties correctly
338                         CopyRelations (Copy);
339
340                         return Copy;
341                 }
342
343                 [MonoTODO]
344                 private void CopyProperties (DataSet Copy)
345                 {
346                         Copy.CaseSensitive = CaseSensitive;
347                         //Copy.Container = Container
348                         Copy.DataSetName = DataSetName;
349                         //Copy.DefaultViewManager
350                         //Copy.DesignMode
351                         Copy.EnforceConstraints = EnforceConstraints;
352                         //Copy.ExtendedProperties 
353                         //Copy.HasErrors
354                         //Copy.Locale = Locale;
355                         Copy.Namespace = Namespace;
356                         Copy.Prefix = Prefix;                   
357                         //Copy.Site = Site;
358
359                 }
360                 
361                 
362                 private void CopyRelations (DataSet Copy)
363                 {
364
365                         //Creation of the relation contains some of the properties, and the constructor
366                         //demands these values. instead changing the DataRelation constructor and behaviour the
367                         //parameters are pre-configured and sent to the most general constructor
368
369                         foreach (DataRelation MyRelation in this.Relations) {
370                                 string pTable = MyRelation.ParentTable.TableName;
371                                 string cTable = MyRelation.ChildTable.TableName;
372                                 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length]; 
373                                 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
374                                 int i = 0;
375                                 
376                                 foreach (DataColumn DC in MyRelation.ParentColumns) {
377                                         P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
378                                         i++;
379                                 }
380
381                                 i = 0;
382
383                                 foreach (DataColumn DC in MyRelation.ChildColumns) {
384                                         C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
385                                         i++;
386                                 }
387                                 
388                                 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
389                                 //cRel.ChildColumns = MyRelation.ChildColumns;
390                                 //cRel.ChildTable = MyRelation.ChildTable;
391                                 //cRel.ExtendedProperties = cRel.ExtendedProperties; 
392                                 //cRel.Nested = MyRelation.Nested;
393                                 //cRel.ParentColumns = MyRelation.ParentColumns;
394                                 //cRel.ParentTable = MyRelation.ParentTable;
395                                                                 
396                                 Copy.Relations.Add (cRel);
397                         }
398                 }
399
400                 
401
402
403                 public DataSet GetChanges ()
404                 {
405                         return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
406                 }
407
408                 
409                 public DataSet GetChanges (DataRowState rowStates)
410                 {
411                         if (!HasChanges (rowStates))
412                                 return null;
413                         
414                         DataSet copySet = Clone ();
415                         IEnumerator tableEnumerator = Tables.GetEnumerator ();
416                         DataTable origTable;
417                         DataTable copyTable;
418                         while (tableEnumerator.MoveNext ()) {
419                                 origTable = (DataTable)tableEnumerator.Current;
420                                 copyTable = copySet.Tables[origTable.TableName];
421
422                                 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
423                                 while (rowEnumerator.MoveNext ()) {
424                                         DataRow row = (DataRow)rowEnumerator.Current;
425                                         if (row.IsRowChanged (rowStates)) {
426                                                 DataRow newRow = copyTable.NewRow ();
427                                                 copyTable.Rows.Add (newRow);
428                                                 row.CopyValuesToRow (newRow);
429                                         }
430                                 }
431                         }
432                         return copySet;
433                 }
434
435 #if NET_1_2
436                 [MonoTODO]
437                 public DataTableReader GetDataReader (DataTable[] dataTables)
438                 {
439                         throw new NotImplementedException ();
440                 }
441
442                 [MonoTODO]
443                 public DataTableReader GetDataReader ()
444                 {
445                         throw new NotImplementedException ();
446                 }
447 #endif
448                 
449                 public string GetXml ()
450                 {
451                         StringWriter Writer = new StringWriter ();
452
453                         // Sending false for not printing the Processing instruction
454                         WriteXml (Writer, XmlWriteMode.IgnoreSchema, false);
455                         return Writer.ToString ();
456                 }
457
458                 public string GetXmlSchema ()
459                 {
460                         StringWriter Writer = new StringWriter ();
461                         WriteXmlSchema (Writer);
462                         return Writer.ToString ();
463                 }
464
465                 [MonoTODO]
466                 public bool HasChanges ()
467                 {
468                         return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
469                 }
470
471                 [MonoTODO]
472                 public bool HasChanges (DataRowState rowState)
473                 {
474                         if (((int)rowState & 0xffffffe0) != 0)
475                                 throw new ArgumentOutOfRangeException ("rowState");
476
477                         DataTableCollection tableCollection = Tables;
478                         DataTable table;
479                         DataRowCollection rowCollection;
480                         DataRow row;
481
482                         for (int i = 0; i < tableCollection.Count; i++) {
483                                 table = tableCollection[i];
484                                 rowCollection = table.Rows;
485                                 for (int j = 0; j < rowCollection.Count; j++) {
486                                         row = rowCollection[j];
487                                         if ((row.RowState & rowState) != 0)
488                                                 return true;
489                                 }
490                         }
491
492                         return false;           
493                 }
494
495                 [MonoTODO]
496                 public void InferXmlSchema (XmlReader reader, string[] nsArray)
497                 {
498                 }
499
500                 public void InferXmlSchema (Stream stream, string[] nsArray)
501                 {
502                         InferXmlSchema (new XmlTextReader (stream), nsArray);
503                 }
504
505                 public void InferXmlSchema (TextReader reader, string[] nsArray)
506                 {
507                         InferXmlSchema (new XmlTextReader (reader), nsArray);
508                 }
509
510                 public void InferXmlSchema (string fileName, string[] nsArray)
511                 {
512                         XmlTextReader reader = new XmlTextReader (fileName);
513                         try {
514                                 InferXmlSchema (reader, nsArray);
515                         } finally {
516                                 reader.Close ();
517                         }
518                 }
519
520 #if NET_1_2
521                 [MonoTODO]
522                 public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
523                 {
524                         throw new NotImplementedException ();
525                 }
526
527                 [MonoTODO]
528                 public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
529                 {
530                         throw new NotImplementedException ();
531                 }
532 #endif
533
534                 public virtual void RejectChanges ()
535                 {
536                         int i;
537                         bool oldEnforceConstraints = this.EnforceConstraints;
538                         this.EnforceConstraints = false;
539                         
540                         for (i = 0; i < this.Tables.Count;i++) 
541                                 this.Tables[i].RejectChanges ();
542
543                         this.EnforceConstraints = oldEnforceConstraints;
544                 }
545
546                 public virtual void Reset ()
547                 {
548                         IEnumerator constraintEnumerator;
549
550                         // first we remove all ForeignKeyConstraints (if we will not do that
551                         // we will get an exception when clearing the tables).
552                         for (int i = 0; i < Tables.Count; i++) {
553                                 ConstraintCollection cc = Tables[i].Constraints;
554                                 for (int j = 0; j < cc.Count; j++) {
555                                         if (cc[j] is ForeignKeyConstraint)
556                                                 cc.Remove (cc[j]);
557                                 }
558                         }
559
560                         Clear ();
561                         Relations.Clear ();
562                         Tables.Clear ();
563                 }
564
565                 public void WriteXml (Stream stream)
566                 {
567                         XmlWriter writer = new XmlTextWriter (stream, null);
568                         
569                         WriteXml (writer);
570                 }
571
572                 ///<summary>
573                 /// Writes the current data for the DataSet to the specified file.
574                 /// </summary>
575                 /// <param name="filename">Fully qualified filename to write to</param>
576                 public void WriteXml (string fileName)
577                 {
578                         XmlWriter writer = new XmlTextWriter (fileName, null);
579                         
580                         WriteXml (writer);
581                         
582                         writer.Close ();
583                 }
584
585                 public void WriteXml (TextWriter writer)
586                 {
587                         XmlWriter xwriter = new XmlTextWriter (writer);
588                         
589                         WriteXml (xwriter);
590                 }
591
592                 public void WriteXml (XmlWriter writer)
593                 {
594                         WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
595                 }
596
597                 public void WriteXml (string filename, XmlWriteMode mode)
598                 {
599                         XmlWriter writer = new XmlTextWriter (filename, null);
600                         WriteXml (writer, mode, true);
601                 }
602
603                 public void WriteXml (Stream stream, XmlWriteMode mode)
604                 {
605                         XmlWriter writer = new XmlTextWriter (stream, null);
606
607                         WriteXml (writer, mode, true);
608                 }
609
610                 public void WriteXml (TextWriter writer, XmlWriteMode mode)
611                 {
612                         XmlWriter xwriter = new XmlTextWriter (writer);
613                         WriteXml (xwriter, mode, true);
614                 }
615
616                 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
617                 {
618                         WriteXml (writer, mode, true);
619                 }
620                 
621                 internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
622                 {
623                         XmlWriter writer = new XmlTextWriter (stream, null);
624                         
625                         WriteXml (writer, mode, writePI);
626                 }
627
628                 internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
629                 {
630                         XmlWriter writer = new XmlTextWriter (fileName, null);
631                         
632                         WriteXml (writer, mode, writePI);
633                         
634                         writer.Close ();
635                 }
636
637                 internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
638                 {
639                         XmlWriter xwriter = new XmlTextWriter (writer);
640                         
641                         WriteXml (xwriter, mode, writePI);
642                 }
643
644                 internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
645                 {
646                         if (writePI && (writer.WriteState == WriteState.Start))
647                                 writer.WriteStartDocument (true);
648
649                         ((XmlTextWriter)writer).Formatting = Formatting.Indented;
650
651                         if (mode == XmlWriteMode.DiffGram) {
652                                 SetRowsID();
653                                 WriteDiffGramElement(writer);
654                         }
655
656                         WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
657                         
658                         if (mode == XmlWriteMode.WriteSchema) {
659                                 DoWriteXmlSchema (writer);
660                         }
661                         
662                         WriteTables (writer, mode, Tables, DataRowVersion.Default);
663                         if (mode == XmlWriteMode.DiffGram) {
664                                 writer.WriteEndElement (); //DataSet name
665                                 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
666
667                                         DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);   
668                                         WriteStartElement (writer, XmlWriteMode.DiffGram, Namespace, Prefix, "diffgr:before");
669                                         WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
670                                         writer.WriteEndElement ();
671                                 }
672                         }
673                         writer.WriteEndElement (); // DataSet name or diffgr:diffgram
674                 }
675
676                 public void WriteXmlSchema (Stream stream)
677                 {
678                         XmlWriter writer = new XmlTextWriter (stream, null );
679                         
680                         WriteXmlSchema (writer);        
681                 }
682
683                 public void WriteXmlSchema (string fileName)
684                 {
685                         XmlWriter writer = new XmlTextWriter (fileName, null);
686                 
687                         WriteXmlSchema (writer);
688                 }
689
690                 public void WriteXmlSchema (TextWriter writer)
691                 {
692                         XmlWriter xwriter = new XmlTextWriter (writer);
693                         
694                         WriteXmlSchema (xwriter);
695                 }
696
697                 public void WriteXmlSchema (XmlWriter writer)
698                 {
699                         ((XmlTextWriter)writer).Formatting = Formatting.Indented;
700                         //Create a skeleton doc and then write the schema 
701                         //proper which is common to the WriteXml method in schema mode
702                         writer.WriteStartDocument ();
703                         
704                         DoWriteXmlSchema (writer);
705                         
706                         writer.WriteEndDocument ();
707                 }
708
709                 public void ReadXmlSchema (Stream stream)
710                 {
711                         XmlReader reader = new XmlTextReader (stream, null);
712                         ReadXmlSchema (reader);
713                 }
714
715                 public void ReadXmlSchema (string str)
716                 {
717                         XmlReader reader = new XmlTextReader (str);
718                         ReadXmlSchema (reader);
719                 }
720
721                 public void ReadXmlSchema (TextReader treader)
722                 {
723                         XmlReader reader = new XmlTextReader (treader);
724                         ReadXmlSchema (reader);                 
725                 }
726
727                 public void ReadXmlSchema (XmlReader reader)
728                 {
729                         XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
730                         SchemaMapper.Read (reader);
731                 }
732
733                 public XmlReadMode ReadXml (Stream stream)
734                 {
735                         return ReadXml (new XmlTextReader (stream));
736                 }
737
738                 public XmlReadMode ReadXml (string str)
739                 {
740                         return ReadXml (new XmlTextReader (str));
741                 }
742
743                 public XmlReadMode ReadXml (TextReader reader)
744                 {
745                         return ReadXml (new XmlTextReader (reader));
746                 }
747
748                 public XmlReadMode ReadXml (XmlReader r)
749                 {
750                         XmlDataLoader Loader = new XmlDataLoader (this);
751                         // FIXME: somekinda exception?
752                         if (!r.Read ())
753                                 return XmlReadMode.Auto; // FIXME
754
755                         /*\
756                          *  If document is diffgram we will use diffgram
757                         \*/
758                         if (r.LocalName == "diffgram")
759                                 return ReadXml (r, XmlReadMode.DiffGram);
760
761                         /*\
762                          *  If we already have a schema, or the document 
763                          *  contains an in-line schema, sets XmlReadMode to ReadSchema.
764                         \*/
765
766                         // FIXME: is this always true: "if we have tables we have to have schema also"
767                         if (Tables.Count > 0)                           
768                                 return ReadXml (r, XmlReadMode.ReadSchema);
769
770                         /*\
771                          *  If we dont have a schema yet and document 
772                          *  contains no inline-schema  mode is XmlReadMode.InferSchema
773                         \*/
774
775                         return ReadXml (r, XmlReadMode.InferSchema);
776
777                 }
778
779                 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
780                 {
781                         return ReadXml (new XmlTextReader (stream), mode);
782                 }
783
784                 public XmlReadMode ReadXml (string str, XmlReadMode mode)
785                 {
786                         return ReadXml (new XmlTextReader (str), mode);
787                 }
788
789                 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
790                 {
791                         return ReadXml (new XmlTextReader (reader), mode);
792                 }
793
794                 [MonoTODO]
795                 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
796                 {
797                         XmlReadMode Result = XmlReadMode.Auto;
798
799                         if (mode == XmlReadMode.DiffGram) {
800                                 if (reader.LocalName != "diffgram"){
801                                         reader.MoveToContent ();
802                                         reader.ReadStartElement ();     // <DataSet>
803
804                                         reader.MoveToContent ();
805                                         ReadXmlSchema (reader);
806
807                                         reader.MoveToContent ();
808                                 }
809                                 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
810                                 DiffLoader.Load (reader);
811                                 Result =  XmlReadMode.DiffGram;
812                         }
813                         else {
814                                 XmlDataLoader Loader = new XmlDataLoader (this);
815                                 Result = Loader.LoadData (reader, mode);
816                         }
817
818                         return Result;
819                 }
820
821                 #endregion // Public Methods
822
823                 #region Public Events
824
825                 [DataCategory ("Action")]
826                 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
827                 public event MergeFailedEventHandler MergeFailed;
828
829                 #endregion // Public Events
830
831                 #region Destructors
832
833                 ~DataSet ()
834                 {
835                 }
836
837                 #endregion Destructors
838
839                 #region IListSource methods
840                 IList IListSource.GetList ()
841                 {
842                         return DefaultViewManager;
843                 }
844                 
845                 bool IListSource.ContainsListCollection {
846                         get {
847                                 return true;
848                         }
849                 }
850                 #endregion IListSource methods
851                 
852                 #region ISupportInitialize methods
853                 public void BeginInit ()
854                 {
855                 }
856                 
857                 public void EndInit ()
858                 {
859                 }
860                 #endregion
861
862                 #region ISerializable
863                 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
864                 {
865                         throw new NotImplementedException ();
866                 }
867                 #endregion
868                 
869                 #region Protected Methods
870                 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
871                 {
872                         string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
873                         if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s)));
874                 }
875                 
876                 
877                 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
878                 {
879                         return BuildSchema ();
880                 }
881                 
882                 protected virtual void ReadXmlSerializable (XmlReader reader)
883                 {
884                         ReadXml (reader, XmlReadMode.DiffGram); // FIXME
885                 }
886
887                 void IXmlSerializable.ReadXml (XmlReader reader)
888                 {
889
890                         ReadXml (reader, XmlReadMode.DiffGram);
891                         
892                         // the XmlSerializationReader does this lines!!!
893                         //reader.MoveToContent ();
894                         //reader.ReadEndElement ();     // </DataSet>
895                 }
896                 
897                 void IXmlSerializable.WriteXml (XmlWriter writer)
898                 {
899                         DoWriteXmlSchema (writer);
900                         WriteXml (writer, XmlWriteMode.DiffGram, true);
901                 }
902
903                 protected virtual bool ShouldSerializeRelations ()
904                 {
905                         return true;
906                 }
907                 
908                 protected virtual bool ShouldSerializeTables ()
909                 {
910                         return true;
911                 }
912
913                 [MonoTODO]
914                 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
915                 {
916                 }
917
918                 [MonoTODO]
919                 protected virtual void OnRemoveRelation (DataRelation relation)
920                 {
921                 }
922
923                 [MonoTODO]
924                 protected virtual void OnRemoveTable (DataTable table)
925                 {
926                 }
927
928                 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
929                 {
930                         if (MergeFailed != null)
931                                 MergeFailed (this, e);
932                 }
933
934                 [MonoTODO]
935                 protected internal void RaisePropertyChanging (string name)
936                 {
937                 }
938                 #endregion
939
940                 #region Private Xml Serialisation
941
942                 private string WriteObjectXml (object o)
943                 {
944                         switch (Type.GetTypeCode (o.GetType ())) {
945                                 case TypeCode.Boolean:
946                                         return XmlConvert.ToString ((Boolean) o);
947                                 case TypeCode.Byte:
948                                         return XmlConvert.ToString ((Byte) o);
949                                 case TypeCode.Char:
950                                         return XmlConvert.ToString ((Char) o);
951                                 case TypeCode.DateTime:
952                                         return XmlConvert.ToString ((DateTime) o);
953                                 case TypeCode.Decimal:
954                                         return XmlConvert.ToString ((Decimal) o);
955                                 case TypeCode.Double:
956                                         return XmlConvert.ToString ((Double) o);
957                                 case TypeCode.Int16:
958                                         return XmlConvert.ToString ((Int16) o);
959                                 case TypeCode.Int32:
960                                         return XmlConvert.ToString ((Int32) o);
961                                 case TypeCode.Int64:
962                                         return XmlConvert.ToString ((Int64) o);
963                                 case TypeCode.SByte:
964                                         return XmlConvert.ToString ((SByte) o);
965                                 case TypeCode.Single:
966                                         return XmlConvert.ToString ((Single) o);
967                                 case TypeCode.UInt16:
968                                         return XmlConvert.ToString ((UInt16) o);
969                                 case TypeCode.UInt32:
970                                         return XmlConvert.ToString ((UInt32) o);
971                                 case TypeCode.UInt64:
972                                         return XmlConvert.ToString ((UInt64) o);
973                         }
974                         if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
975                         if (o is Guid) return XmlConvert.ToString ((Guid) o);
976                         return o.ToString ();
977                 }
978                 
979                 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
980                 {
981                         //Write out each table in order, providing it is not
982                         //part of another table structure via a nested parent relationship
983                         foreach (DataTable table in tableCollection) {
984                                 bool isTopLevel = true;
985                                 foreach (DataRelation rel in table.ParentRelations) {
986                                         if (rel.Nested) {
987                                                 isTopLevel = false;
988                                                 break;
989                                         }
990                                 }
991                                 
992                                 if (isTopLevel) {
993                                         WriteTable ( writer, table, mode, version);
994                                 }
995                         }
996                 }
997
998                 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
999                 {
1000                         DataRow[] rows = new DataRow [table.Rows.Count];
1001                         table.Rows.CopyTo (rows, 0);
1002                         WriteTable (writer, rows, mode, version);
1003                 }
1004
1005                 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1006                 {
1007                         //The columns can be attributes, hidden, elements, or simple content
1008                         //There can be 0-1 simple content cols or 0-* elements
1009                         System.Collections.ArrayList atts;
1010                         System.Collections.ArrayList elements;
1011                         DataColumn simple = null;
1012
1013                         if (rows.Length == 0) return;
1014                         DataTable table = rows[0].Table;
1015                         SplitColumns (table, out atts, out elements, out simple);
1016                         //sort out the namespacing
1017                         string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1018
1019                         foreach (DataRow row in rows) {
1020                                 if (!row.HasVersion(version))
1021                                         continue;
1022                                 
1023                                 // First check are all the rows null. If they are we just write empty element
1024                                 bool AllNulls = true;
1025                                 foreach (DataColumn dc in table.Columns) {
1026                                 
1027                                         if (row [dc.ColumnName, version] != DBNull.Value) {
1028                                                 AllNulls = false;
1029                                                 break;
1030                                         } 
1031                                 }
1032
1033                                 // If all of the columns were null, we have to write empty element
1034                                 if (AllNulls) {
1035                                         writer.WriteElementString (table.TableName, "");
1036                                         continue;
1037                                 }
1038                                 
1039                                 WriteTableElement (writer, mode, table, row, version);
1040                                 
1041                                 foreach (DataColumn col in atts) {                                      
1042                                         WriteColumnAsAttribute (writer, mode, col, row, version);
1043                                 }
1044                                 
1045                                 if (simple != null) {
1046                                         writer.WriteString (WriteObjectXml (row[simple, version]));
1047                                 }
1048                                 else {                                  
1049                                         foreach (DataColumn col in elements) {
1050                                                 WriteColumnAsElement (writer, mode, nspc, col, row, version);
1051                                         }
1052                                 }
1053                                 
1054                                 foreach (DataRelation relation in table.ChildRelations) {
1055                                         if (relation.Nested) {
1056                                                 WriteTable (writer, row.GetChildRows (relation), mode, version);
1057                                         }
1058                                 }
1059                                 
1060                                 writer.WriteEndElement ();
1061                         }
1062
1063                 }
1064
1065                 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
1066                 {
1067                         string colnspc = nspc;
1068                         object rowObject = row [col, version];
1069                                                                         
1070                         if (rowObject == null || rowObject == DBNull.Value)
1071                                 return;
1072
1073                         if (col.Namespace != null) {
1074                                 colnspc = col.Namespace;
1075                         }
1076         
1077                         //TODO check if I can get away with write element string
1078                         WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName);
1079                         writer.WriteString (WriteObjectXml (rowObject));
1080                         writer.WriteEndElement ();
1081                 }
1082
1083                 private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1084                 {
1085                         WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
1086                 }
1087
1088                 private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
1089                 {
1090                         //sort out the namespacing
1091                         string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1092
1093                         WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
1094
1095                         if (mode == XmlWriteMode.DiffGram) {
1096                                 WriteAttributeString (writer, mode, "", "diffgr", "id", table.TableName + (row.XmlRowID + 1));
1097                                 WriteAttributeString (writer, mode, "", "msdata", "rowOrder", row.XmlRowID.ToString());
1098                                 if (row.RowState == DataRowState.Modified && version != DataRowVersion.Original){
1099                                         WriteAttributeString (writer, mode, "", "diffgr", "hasChanges", "modified");
1100                                 }
1101                         }
1102                 }
1103                     
1104                 private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
1105                 {                       
1106                         switch ( mode) {
1107                                 case XmlWriteMode.WriteSchema:
1108                                         if (nspc == null || nspc == "") {
1109                                                 writer.WriteStartElement (name);
1110                                         }
1111                                         else if (prefix != null) {                                                      
1112                                                 writer.WriteStartElement (prefix, name, nspc);
1113                                         }                                               
1114                                         else {                                  
1115                                                 writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
1116                                         }
1117                                         break;
1118                                 case XmlWriteMode.DiffGram:
1119                                         writer.WriteStartElement (name);
1120                                         break;  
1121                                 default:                                               
1122                                         writer.WriteStartElement (name);
1123                                         break;                                  
1124                         };
1125                 }
1126                 
1127                 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1128                 {
1129                         switch ( mode) {
1130                                 case XmlWriteMode.WriteSchema:
1131                                         writer.WriteAttributeString (prefix, name, nspc);
1132                                         break;
1133                                 case XmlWriteMode.DiffGram:
1134                                         writer.WriteAttributeString (prefix, name, nspc, stringValue);
1135                                         break;
1136                                 default:
1137                                         writer.WriteAttributeString (name, stringValue);
1138                                         break;                                  
1139                         };
1140                 }
1141
1142                 XmlSchema IXmlSerializable.GetSchema ()
1143                 {
1144                         return BuildSchema ();
1145                 }
1146                 
1147                 XmlSchema BuildSchema ()
1148                 {
1149                         XmlSchema schema = new XmlSchema ();
1150                         schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1151
1152                         XmlSchemaElement elem = new XmlSchemaElement ();
1153                         elem.Name = XmlConvert.EncodeName (DataSetName);
1154
1155                         XmlDocument doc = new XmlDocument ();
1156
1157                         XmlAttribute[] atts = new XmlAttribute [2];
1158                         atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1159                         atts[0].Value = "true";
1160
1161                         atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1162                         atts[1].Value = locale.Name;
1163                         elem.UnhandledAttributes = atts;
1164
1165                         schema.Items.Add (elem);
1166
1167                         XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1168                         elem.SchemaType = complex;
1169
1170                         XmlSchemaChoice choice = new XmlSchemaChoice ();
1171                         complex.Particle = choice;
1172                         choice.MaxOccursString = XmlConstants.Unbounded;
1173                         
1174                         //Write out schema for each table in order
1175                         foreach (DataTable table in Tables) {           
1176                                 bool isTopLevel = true;
1177                                 foreach (DataRelation rel in table.ParentRelations) {
1178                                         if (rel.Nested) {
1179                                                 isTopLevel = false;
1180                                                 break;
1181                                         }
1182                                 }
1183                                 
1184                                 if (isTopLevel){
1185                                         choice.Items.Add (GetTableSchema (doc, table));
1186                                 }
1187                         }
1188                         
1189                         bool nameModifier = true;
1190                         foreach (DataRelation rel in Relations) {
1191                                 XmlSchemaUnique uniq = new XmlSchemaUnique();
1192                                 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1193                                 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1194                                 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1195                                                                 
1196                                 if (nameModifier) {
1197                                         uniq.Name = uqConst.ConstraintName;
1198                                         keyRef.Name = fkConst.ConstraintName;
1199                                         keyRef.Refer = new XmlQualifiedName(uniq.Name);
1200                                         XmlAttribute[] attrib = null;
1201                                         if (rel.Nested){
1202                                                 attrib = new XmlAttribute [2];
1203                                                 attrib [0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1204                                                 attrib [0].Value = "true";
1205                 
1206                                                 attrib [1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.RelationName, XmlConstants.MsdataNamespace);
1207                                                 attrib [1].Value = rel.RelationName;
1208                                         }
1209                                         else {
1210                                                 attrib = new XmlAttribute [1];
1211                                                 attrib[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.RelationName, XmlConstants.MsdataNamespace);
1212                                                 attrib[0].Value = rel.RelationName;
1213
1214                                         }
1215                                         keyRef.UnhandledAttributes = attrib;
1216                                         nameModifier = false;
1217                                 }
1218                                 else {
1219                                         uniq.Name = rel.ParentTable.TableName+"_"+uqConst.ConstraintName;
1220                                         keyRef.Name = rel.ChildTable.TableName+"_"+fkConst.ConstraintName;
1221                                         keyRef.Refer = new XmlQualifiedName(uniq.Name);
1222                                         XmlAttribute[] attrib;
1223                                         if (rel.Nested) {
1224                                                 attrib = new XmlAttribute [3];
1225                                                 attrib [0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1226                                                 attrib [0].Value = fkConst.ConstraintName;
1227                                                 attrib [1] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1228                                                 attrib [1].Value = "true";
1229                 
1230                                                 attrib [2] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.RelationName, XmlConstants.MsdataNamespace);
1231                                                 attrib [2].Value = rel.RelationName;
1232                                         }
1233                                         else {
1234                                                 attrib = new XmlAttribute [2];
1235                                                 attrib [0] = doc.CreateAttribute (XmlConstants.MsdataPrefix,  XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1236                                                 attrib [0].Value = fkConst.ConstraintName;
1237                                                 attrib [1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.RelationName, XmlConstants.MsdataNamespace);
1238                                                 attrib [1].Value = rel.RelationName;
1239
1240                                         }
1241                                         keyRef.UnhandledAttributes = attrib;
1242                                         attrib = new XmlAttribute [1];
1243                                         attrib [0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1244                                         attrib [0].Value = uqConst.ConstraintName; 
1245                                         uniq.UnhandledAttributes = attrib;
1246                                 }
1247
1248                                 uniq.Selector = new XmlSchemaXPath();
1249                                 uniq.Selector.XPath = ".//"+rel.ParentTable.TableName;
1250                                 XmlSchemaXPath field;
1251                                 foreach (DataColumn column in rel.ParentColumns) {
1252                                         field = new XmlSchemaXPath();
1253                                         field.XPath = column.ColumnName;
1254                                         uniq.Fields.Add(field);
1255                                 }
1256                                 
1257                                 keyRef.Selector = new XmlSchemaXPath();
1258                                 keyRef.Selector.XPath = ".//"+rel.ChildTable.TableName;
1259                                 foreach (DataColumn column in rel.ChildColumns) {
1260                                         field = new XmlSchemaXPath();
1261                                         field.XPath = column.ColumnName;
1262                                         keyRef.Fields.Add(field);
1263                                 }
1264                                 
1265                                 elem.Constraints.Add (uniq);
1266                                 elem.Constraints.Add (keyRef);
1267                         }
1268                         
1269                         return schema;
1270                 }
1271
1272                 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1273                 {
1274                         ArrayList elements;
1275                         ArrayList atts;
1276                         DataColumn simple;
1277                         
1278                         SplitColumns (table, out atts, out elements, out simple);
1279
1280                         XmlSchemaElement elem = new XmlSchemaElement ();
1281                         elem.Name = table.TableName;
1282
1283                         XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1284                         elem.SchemaType = complex;
1285
1286                         //TODO - what about the simple content?
1287                         if (elements.Count == 0) {                              
1288                         }
1289                         else {
1290                                 //A sequence of element types or a simple content node
1291                                 //<xs:sequence>
1292                                 XmlSchemaSequence seq = new XmlSchemaSequence ();
1293                                 complex.Particle = seq;
1294
1295                                 foreach (DataColumn col in elements) {
1296                                         //<xs:element name=ColumnName type=MappedType Ordinal=index>
1297                                         XmlSchemaElement colElem = new XmlSchemaElement ();
1298                                         colElem.Name = col.ColumnName;
1299                                 
1300                                         if (col.ColumnName != col.Caption && col.Caption != string.Empty) {
1301                                                 XmlAttribute[] xatts = new XmlAttribute[1];
1302                                                 xatts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1303                                                 xatts[0].Value = col.Caption;
1304                                                 colElem.UnhandledAttributes = xatts;
1305                                         }
1306
1307                                         if (col.DefaultValue.ToString () != string.Empty)
1308                                                 colElem.DefaultValue = col.DefaultValue.ToString ();
1309
1310                                         colElem.SchemaTypeName = MapType (col.DataType);
1311
1312                                         if (col.AllowDBNull) {
1313                                                 colElem.MinOccurs = 0;
1314                                         }
1315
1316                                         //writer.WriteAttributeString (XmlConstants.MsdataPrefix, 
1317                                         //                            XmlConstants.Ordinal, 
1318                                         //                            XmlConstants.MsdataNamespace, 
1319                                         //                            col.Ordinal.ToString ());
1320
1321                                         // Write SimpleType if column have MaxLength
1322                                         if (col.MaxLength > -1) {
1323                                                 colElem.SchemaType = GetTableSimpleType (doc, col);
1324                                         }
1325
1326                                         seq.Items.Add (colElem);
1327                                 }
1328
1329                                 foreach (DataRelation rel in table.ChildRelations) {
1330                                         if (rel.Nested) {
1331                                                 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1332                                         }
1333                                 }
1334                         }
1335
1336                         //Then a list of attributes
1337                         foreach (DataColumn col in atts) {
1338                                 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1339                                 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1340                                 att.Name = col.ColumnName;
1341                                 att.Form = XmlSchemaForm.Unqualified;
1342                                 att.SchemaTypeName = MapType (col.DataType);
1343                                 complex.Attributes.Add (att);
1344                         }
1345
1346                         return elem;
1347                 }
1348
1349                 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1350                 {
1351                         // SimpleType
1352                         XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1353
1354                         // Restriction
1355                         XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1356                         restriction.BaseTypeName = MapType (col.DataType);
1357                         
1358                         // MaxValue
1359                         XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1360                         max.Value = XmlConvert.ToString (col.MaxLength);
1361                         restriction.Facets.Add (max);
1362
1363                         return simple;
1364                 }
1365
1366                 private void DoWriteXmlSchema (XmlWriter writer)
1367                 {
1368                         GetSchemaSerializable ().Write (writer);
1369                 }
1370                 
1371                 ///<summary>
1372                 /// Helper function to split columns into attributes elements and simple
1373                 /// content
1374                 /// </summary>
1375                 private void SplitColumns (DataTable table, 
1376                         out ArrayList atts, 
1377                         out ArrayList elements, 
1378                         out DataColumn simple)
1379                 {
1380                         //The columns can be attributes, hidden, elements, or simple content
1381                         //There can be 0-1 simple content cols or 0-* elements
1382                         atts = new System.Collections.ArrayList ();
1383                         elements = new System.Collections.ArrayList ();
1384                         simple = null;
1385                         
1386                         //Sort out the columns
1387                         foreach (DataColumn col in table.Columns) {
1388                                 switch (col.ColumnMapping) {
1389                                         case MappingType.Attribute:
1390                                                 atts.Add (col);
1391                                                 break;
1392                                         case MappingType.Element:
1393                                                 elements.Add (col);
1394                                                 break;
1395                                         case MappingType.SimpleContent:
1396                                                 if (simple != null) {
1397                                                         throw new System.InvalidOperationException ("There may only be one simple content element");
1398                                                 }
1399                                                 simple = col;
1400                                                 break;
1401                                         default:
1402                                                 //ignore Hidden elements
1403                                                 break;
1404                                 }
1405                         }
1406                 }
1407
1408                 private void WriteDiffGramElement(XmlWriter writer)
1409                 {
1410                         WriteStartElement (writer, XmlWriteMode.DiffGram, Namespace, Prefix, "diffgr:diffgram");
1411                         WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1412                         WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.DiffgrPrefix, XmlConstants.DiffgrNamespace);
1413                 }
1414
1415                 private void SetRowsID()
1416                 {
1417                         foreach (DataTable Table in Tables) {
1418                                 int dataRowID = 0;
1419                                 foreach (DataRow Row in Table.Rows) {
1420                                         Row.XmlRowID = dataRowID;
1421                                         dataRowID++;
1422                                 }
1423                         }
1424                 }
1425
1426                 
1427                 private XmlQualifiedName MapType (Type type)
1428                 {
1429                         switch (Type.GetTypeCode (type)) {
1430                                 case TypeCode.String: return XmlConstants.QnString;
1431                                 case TypeCode.Int16: return XmlConstants.QnShort;
1432                                 case TypeCode.Int32: return XmlConstants.QnInt;
1433                                 case TypeCode.Int64: return XmlConstants.QnLong;
1434                                 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1435                                 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1436                                 case TypeCode.Char: return XmlConstants.QnChar;
1437                                 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1438                                 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1439                                 case TypeCode.Double: return XmlConstants.QnDouble;
1440                                 case TypeCode.SByte: return XmlConstants.QnSbyte;
1441                                 case TypeCode.Single: return XmlConstants.QnFloat;
1442                                 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1443                                 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1444                                 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1445                         }
1446                         
1447                         if (typeof (TimeSpan) == type)
1448                                 return XmlConstants.QnDuration;
1449                         else if (typeof (System.Uri) == type)
1450                                 return XmlConstants.QnUri;
1451                         else if (typeof (byte[]) == type)
1452                                 return XmlConstants.QnBase64Binary;
1453                         else if (typeof (XmlQualifiedName) == type)
1454                                 return XmlConstants.QnXmlQualifiedName;
1455                         else
1456                                 return XmlConstants.QnString;
1457                 }
1458
1459                 #endregion //Private Xml Serialisation
1460         }
1461 }