BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / System.Data / System.Data / DataSet.cs
1 //\r
2 // System.Data/DataSet.cs\r
3 //\r
4 // Author:\r
5 //   Christopher Podurgiel <cpodurgiel@msn.com>\r
6 //   Daniel Morgan <danmorg@sc.rr.com>\r
7 //   Rodrigo Moya <rodrigo@ximian.com>\r
8 //   Stuart Caborn <stuart.caborn@virgin.net>\r
9 //   Tim Coleman (tim@timcoleman.com)\r
10 //   Ville Palo <vi64pa@koti.soon.fi>\r
11 //   Atsushi Enomoto <atsushi@ximian.com>\r
12 //   Konstantin Triger <kostat@mainsoft.com>\r
13 //\r
14 // (C) Ximian, Inc. 2002\r
15 // Copyright (C) Tim Coleman, 2002, 2003\r
16 //\r
17 \r
18 //\r
19 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
20 //\r
21 // Permission is hereby granted, free of charge, to any person obtaining\r
22 // a copy of this software and associated documentation files (the\r
23 // "Software"), to deal in the Software without restriction, including\r
24 // without limitation the rights to use, copy, modify, merge, publish,\r
25 // distribute, sublicense, and/or sell copies of the Software, and to\r
26 // permit persons to whom the Software is furnished to do so, subject to\r
27 // the following conditions:\r
28 //\r
29 // The above copyright notice and this permission notice shall be\r
30 // included in all copies or substantial portions of the Software.\r
31 //\r
32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
33 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
34 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
35 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
36 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
37 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
38 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
39 //\r
40 \r
41 using System;\r
42 using System.Collections;\r
43 using System.ComponentModel;\r
44 using System.Globalization;\r
45 using System.Threading;\r
46 using System.IO;\r
47 using System.Runtime.Serialization;\r
48 using System.Runtime.Serialization.Formatters.Binary;\r
49 using System.Xml;\r
50 using System.Xml.Schema;\r
51 using System.Xml.Serialization;\r
52 using System.Data.Common;\r
53 \r
54 namespace System.Data\r
55 {\r
56         [ToolboxItem ("Microsoft.VSDesigner.Data.VS.DataSetToolboxItem, " + Consts.AssemblyMicrosoft_VSDesigner)]\r
57         [DefaultProperty ("DataSetName")]\r
58         [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataSetDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
59         [Serializable]\r
60         public partial class DataSet : MarshalByValueComponent, IListSource, ISupportInitialize,\r
61                                ISerializable, IXmlSerializable {\r
62                 private string dataSetName;\r
63                 private string _namespace = string.Empty;\r
64                 private string prefix;\r
65                 private bool caseSensitive;\r
66                 private bool enforceConstraints = true;\r
67                 private DataTableCollection tableCollection;\r
68                 private DataRelationCollection relationCollection;\r
69                 private PropertyCollection properties;\r
70                 private DataViewManager defaultView;\r
71                 private CultureInfo locale;\r
72                 internal XmlDataDocument _xmlDataDocument;\r
73 \r
74 #if NET_2_0\r
75                 internal TableAdapterSchemaInfo tableAdapterSchemaInfo;\r
76 #endif\r
77                 bool initInProgress;\r
78 \r
79                 #region Constructors\r
80 \r
81                 public DataSet ()\r
82                         : this ("NewDataSet")\r
83                 {\r
84                 }\r
85 \r
86                 public DataSet (string dataSetName)\r
87                 {\r
88                         this.dataSetName = dataSetName;\r
89                         tableCollection = new DataTableCollection (this);\r
90                         relationCollection = new DataRelationCollection.DataSetRelationCollection (this);\r
91                         properties = new PropertyCollection ();\r
92                         prefix = String.Empty;\r
93                 }\r
94 \r
95                 protected DataSet (SerializationInfo info, StreamingContext context)\r
96                         : this ()\r
97                 {\r
98 #if NET_2_0\r
99                         if (IsBinarySerialized (info, context)) {\r
100                                 BinaryDeserialize (info);\r
101                                 return;\r
102                         }\r
103 #endif\r
104                         string s = info.GetValue ("XmlSchema", typeof (String)) as String;\r
105                         XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
106                         ReadXmlSchema (reader);\r
107                         reader.Close ();\r
108 \r
109                         GetSerializationData (info, context);\r
110                 }\r
111 \r
112                 #endregion // Constructors\r
113 \r
114                 #region Public Properties\r
115 \r
116                 [DataCategory ("Data")]\r
117 #if !NET_2_0\r
118                 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]\r
119 #endif\r
120                 [DefaultValue (false)]\r
121                 public bool CaseSensitive {\r
122                         get { return caseSensitive; }\r
123                         set {\r
124                                 caseSensitive = value;\r
125                                 if (!caseSensitive) {\r
126                                         foreach (DataTable table in Tables) {\r
127                                                 table.ResetCaseSensitiveIndexes ();\r
128                                                 foreach (Constraint c in table.Constraints)\r
129                                                         c.AssertConstraint ();\r
130                                         }\r
131                                 } else {\r
132                                         foreach (DataTable table in Tables) {\r
133                                                 table.ResetCaseSensitiveIndexes ();\r
134                                         }\r
135                                 }\r
136                         }\r
137                 }\r
138 \r
139                 [DataCategory ("Data")]\r
140 #if !NET_2_0\r
141                 [DataSysDescription ("The name of this DataSet.")]\r
142 #endif\r
143                 [DefaultValue ("")]\r
144                 public string DataSetName {\r
145                         get { return dataSetName; }\r
146                         set { dataSetName = value; }\r
147                 }\r
148 \r
149 #if !NET_2_0\r
150                 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]\r
151 #endif\r
152                 [Browsable (false)]\r
153                 public DataViewManager DefaultViewManager {\r
154                         get {\r
155                                 if (defaultView == null)\r
156                                         defaultView = new DataViewManager (this);\r
157                                 return defaultView;\r
158                         }\r
159                 }\r
160 \r
161 #if !NET_2_0\r
162                 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]\r
163 #endif\r
164                 [DefaultValue (true)]\r
165                 public bool EnforceConstraints {\r
166                         get { return enforceConstraints; }\r
167                         set { InternalEnforceConstraints (value, true); }\r
168                 }\r
169 \r
170                 [Browsable (false)]\r
171                 [DataCategory ("Data")]\r
172 #if !NET_2_0\r
173                 [DataSysDescription ("The collection that holds custom user information.")]\r
174 #endif\r
175                 public PropertyCollection ExtendedProperties {\r
176                         get { return properties; }\r
177                 }\r
178 \r
179                 [Browsable (false)]\r
180 #if !NET_2_0\r
181                 [DataSysDescription ("Indicates that the DataSet has errors.")]\r
182 #endif\r
183                 public bool HasErrors {\r
184                         get {\r
185                                 for (int i = 0; i < Tables.Count; i++) {\r
186                                         if (Tables[i].HasErrors)\r
187                                                 return true;\r
188                                 }\r
189                                 return false;\r
190                         }\r
191                 }\r
192 \r
193                 [DataCategory ("Data")]\r
194 #if !NET_2_0\r
195                 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]\r
196 #endif\r
197                 public CultureInfo Locale {\r
198                         get { return locale != null ? locale : Thread.CurrentThread.CurrentCulture; }\r
199                         set {\r
200                                 if (locale == null || !locale.Equals (value)) {\r
201                                         // TODO: check if the new locale is valid\r
202                                         // TODO: update locale of all tables\r
203                                         locale = value;\r
204                                 }\r
205                         }\r
206                 }\r
207 \r
208                 internal bool LocaleSpecified {\r
209                         get { return locale != null; }\r
210                 }\r
211 \r
212                 \r
213 #if NET_2_0\r
214                 internal TableAdapterSchemaInfo TableAdapterSchemaData {\r
215                         get { return tableAdapterSchemaInfo; }\r
216                 }\r
217 #endif\r
218                 \r
219                 internal void InternalEnforceConstraints (bool value,bool resetIndexes)\r
220                 {\r
221                         if (value == enforceConstraints)\r
222                                 return;\r
223 \r
224                         if (value) {\r
225                                 if (resetIndexes) {\r
226                                         // FIXME : is that correct?\r
227                                         // By design the indexes should be updated at this point.\r
228                                         // In Fill from BeginLoadData till EndLoadData indexes are not updated (reset in EndLoadData)\r
229                                         // In DataRow.EndEdit indexes are always updated.\r
230                                         foreach (DataTable table in Tables)\r
231                                                 table.ResetIndexes ();\r
232                                 }\r
233 \r
234                                 // TODO : Need to take care of Error handling and settting of RowErrors\r
235                                 bool constraintViolated = false;\r
236                                 foreach (DataTable table in Tables) {\r
237                                         foreach (Constraint constraint in table.Constraints)\r
238                                                 constraint.AssertConstraint();\r
239                                         table.AssertNotNullConstraints ();\r
240                                         if (!constraintViolated && table.HasErrors)\r
241                                                 constraintViolated = true;\r
242                                 }\r
243 \r
244                                 if (constraintViolated)\r
245                                         Constraint.ThrowConstraintException ();\r
246                         }\r
247                         enforceConstraints = value;\r
248                 }\r
249 \r
250                 public void Merge (DataRow[] rows)\r
251                 {\r
252                         Merge (rows, false, MissingSchemaAction.Add);\r
253                 }\r
254 \r
255                 public void Merge (DataSet dataSet)\r
256                 {\r
257                         Merge (dataSet, false, MissingSchemaAction.Add);\r
258                 }\r
259 \r
260                 public void Merge (DataTable table)\r
261                 {\r
262                         Merge (table, false, MissingSchemaAction.Add);\r
263                 }\r
264 \r
265                 public void Merge (DataSet dataSet, bool preserveChanges)\r
266                 {\r
267                         Merge (dataSet, preserveChanges, MissingSchemaAction.Add);\r
268                 }\r
269 \r
270                 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
271                 {\r
272                         if (rows == null)\r
273                                 throw new ArgumentNullException ("rows");\r
274                         if (!IsLegalSchemaAction (missingSchemaAction))\r
275                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
276 \r
277                         MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);\r
278                 }\r
279 \r
280                 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
281                 {\r
282                         if (dataSet == null)\r
283                                 throw new ArgumentNullException ("dataSet");\r
284                         if (!IsLegalSchemaAction (missingSchemaAction))\r
285                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
286 \r
287                         MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);\r
288                 }\r
289 \r
290                 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
291                 {\r
292                         if (table == null)\r
293                                 throw new ArgumentNullException ("table");\r
294                         if (!IsLegalSchemaAction (missingSchemaAction))\r
295                                 throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
296 \r
297                         MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);\r
298                 }\r
299 \r
300                 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)\r
301                 {\r
302                         if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey\r
303                                 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)\r
304                                 return true;\r
305                         return false;\r
306                 }\r
307 \r
308                 [DataCategory ("Data")]\r
309 #if !NET_2_0\r
310                 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]\r
311 #endif\r
312                 [DefaultValue ("")]\r
313                 public string Namespace {\r
314                         get { return _namespace; }\r
315                         set {\r
316                                 //TODO - trigger an event if this happens?\r
317                                 if (value == null)\r
318                                         value = String.Empty;\r
319                                  if (value != this._namespace)\r
320                                         RaisePropertyChanging ("Namespace");\r
321                                 _namespace = value;\r
322                         }\r
323                 }\r
324 \r
325                 [DataCategory ("Data")]\r
326 #if !NET_2_0\r
327                 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]\r
328 #endif\r
329                 [DefaultValue ("")]\r
330                 public string Prefix {\r
331                         get { return prefix; }\r
332                         set {\r
333                                 if (value == null)\r
334                                         value = String.Empty;\r
335                                 // Prefix cannot contain any special characters other than '_' and ':'\r
336                                 for (int i = 0; i < value.Length; i++) {\r
337                                         if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))\r
338                                                 throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");\r
339                                 }\r
340 \r
341                                 if (value != this.prefix)\r
342                                         RaisePropertyChanging ("Prefix");\r
343                                 prefix = value;\r
344                         }\r
345                 }\r
346 \r
347                 [DataCategory ("Data")]\r
348 #if !NET_2_0\r
349                 [DataSysDescription ("The collection that holds the relations for this DatSet.")]\r
350 #endif\r
351                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
352                 public DataRelationCollection Relations {\r
353                         get { return relationCollection; }\r
354                 }\r
355 \r
356                 [Browsable (false)]\r
357                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
358                 public override ISite Site {\r
359                         get { return base.Site; }\r
360                         set { base.Site = value; }\r
361                 }\r
362 \r
363                 [DataCategory ("Data")]\r
364 #if !NET_2_0\r
365                 [DataSysDescription ("The collection that holds the tables for this DataSet.")]\r
366 #endif\r
367                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
368                 public DataTableCollection Tables {\r
369                         get { return tableCollection; }\r
370                 }\r
371 \r
372                 #endregion // Public Properties\r
373 \r
374                 #region Public Methods\r
375 \r
376                 public void AcceptChanges ()\r
377                 {\r
378                         foreach (DataTable tempTable in tableCollection)\r
379                                 tempTable.AcceptChanges ();\r
380                 }\r
381 \r
382                 /// <summary>\r
383                 /// Clears all the tables\r
384                 /// </summary>\r
385                 public void Clear ()\r
386                 {\r
387                         if (_xmlDataDocument != null)\r
388                                 throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet.");\r
389                         bool enforceConstraints = this.EnforceConstraints;\r
390                         this.EnforceConstraints = false;\r
391                         for (int t = 0; t < tableCollection.Count; t++)\r
392                                 tableCollection[t].Clear ();\r
393                         this.EnforceConstraints = enforceConstraints;\r
394                 }\r
395 \r
396                 public virtual DataSet Clone ()\r
397                 {\r
398                         // need to return the same type as this...\r
399                         DataSet Copy = (DataSet) Activator.CreateInstance (GetType (), true);\r
400 \r
401                         CopyProperties (Copy);\r
402 \r
403                         foreach (DataTable Table in Tables) {\r
404                                 // tables are often added in no-args constructor, don't add them\r
405                                 // twice.\r
406                                 if (!Copy.Tables.Contains (Table.TableName))\r
407                                         Copy.Tables.Add (Table.Clone ());\r
408                         }\r
409 \r
410                         //Copy Relationships between tables after existance of tables\r
411                         //and setting properties correctly\r
412                         CopyRelations (Copy);\r
413 \r
414                         return Copy;\r
415                 }\r
416 \r
417                 // Copies both the structure and data for this DataSet.\r
418                 public DataSet Copy ()\r
419                 {\r
420                         // need to return the same type as this...\r
421                         DataSet Copy = (DataSet) Activator.CreateInstance (GetType (), true);\r
422 \r
423                         CopyProperties (Copy);\r
424 \r
425                         // Copy DatSet's tables\r
426                         foreach (DataTable Table in Tables) {\r
427                                 if (! Copy.Tables.Contains (Table.TableName)) {\r
428                                         Copy.Tables.Add (Table.Copy ());\r
429                                         continue;\r
430                                 }\r
431                                 foreach (DataRow row in Table.Rows)\r
432                                         Copy.Tables [Table.TableName].ImportRow (row);\r
433                         }\r
434 \r
435                         //Copy Relationships between tables after existance of tables\r
436                         //and setting properties correctly\r
437                         CopyRelations (Copy);\r
438 \r
439                         return Copy;\r
440                 }\r
441 \r
442                 private void CopyProperties (DataSet Copy)\r
443                 {\r
444                         Copy.CaseSensitive = CaseSensitive;\r
445                         //Copy.Container = Container\r
446                         Copy.DataSetName = DataSetName;\r
447                         //Copy.DefaultViewManager\r
448                         //Copy.DesignMode\r
449                         Copy.EnforceConstraints = EnforceConstraints;\r
450                         if(ExtendedProperties.Count > 0) {\r
451                                 // Cannot copy extended properties directly as the property does not have a set accessor\r
452                                 Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);\r
453                                 ExtendedProperties.Keys.CopyTo (tgtArray, 0);\r
454                                 for (int i = 0; i < ExtendedProperties.Count; i++)\r
455                                         Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);\r
456                         }\r
457                         Copy.locale = locale;\r
458                         Copy.Namespace = Namespace;\r
459                         Copy.Prefix = Prefix;\r
460                         //Copy.Site = Site; // FIXME : Not sure of this.\r
461                 }\r
462 \r
463 \r
464                 private void CopyRelations (DataSet Copy)\r
465                 {\r
466 \r
467                         //Creation of the relation contains some of the properties, and the constructor\r
468                         //demands these values. instead changing the DataRelation constructor and behaviour the\r
469                         //parameters are pre-configured and sent to the most general constructor\r
470 \r
471                         foreach (DataRelation MyRelation in this.Relations) {\r
472 \r
473                                 // typed datasets create relations through ctor.\r
474                                 if (Copy.Relations.Contains (MyRelation.RelationName))\r
475                                         continue;\r
476 \r
477                                 string pTable = MyRelation.ParentTable.TableName;\r
478                                 string cTable = MyRelation.ChildTable.TableName;\r
479                                 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];\r
480                                 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];\r
481                                 int i = 0;\r
482 \r
483                                 foreach (DataColumn DC in MyRelation.ParentColumns) {\r
484                                         P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];\r
485                                         i++;\r
486                                 }\r
487 \r
488                                 i = 0;\r
489 \r
490                                 foreach (DataColumn DC in MyRelation.ChildColumns) {\r
491                                         C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];\r
492                                         i++;\r
493                                 }\r
494 \r
495                                 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC, false);\r
496                                 Copy.Relations.Add (cRel);\r
497                         }\r
498 \r
499                         // Foreign Key constraints are not cloned in DataTable.Clone\r
500                         // so, these constraints should be cloned when copying the relations.\r
501                         foreach (DataTable table in this.Tables) {\r
502                                 foreach (Constraint c in table.Constraints) {\r
503                                         if (!(c is ForeignKeyConstraint)\r
504                                                 || Copy.Tables[table.TableName].Constraints.Contains (c.ConstraintName))\r
505                                                 continue;\r
506                                         ForeignKeyConstraint fc = (ForeignKeyConstraint)c;\r
507                                         DataTable parentTable = Copy.Tables [fc.RelatedTable.TableName];\r
508                                         DataTable currTable = Copy.Tables [table.TableName];\r
509                                         DataColumn[] parentCols = new DataColumn [fc.RelatedColumns.Length];\r
510                                         DataColumn[] childCols = new DataColumn [fc.Columns.Length];\r
511                                         for (int j=0; j < parentCols.Length; ++j)\r
512                                                 parentCols [j] = parentTable.Columns[fc.RelatedColumns[j].ColumnName];\r
513                                         for (int j=0; j < childCols.Length; ++j)\r
514                                                 childCols [j] = currTable.Columns[fc.Columns[j].ColumnName];\r
515                                         currTable.Constraints.Add (fc.ConstraintName, parentCols, childCols);\r
516                                 }\r
517                         }\r
518                 }\r
519 \r
520                 public DataSet GetChanges ()\r
521                 {\r
522                         return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
523                 }\r
524 \r
525 \r
526                 public DataSet GetChanges (DataRowState rowStates)\r
527                 {\r
528                         if (!HasChanges (rowStates))\r
529                                 return null;\r
530 \r
531                         DataSet copySet = Clone ();\r
532                         bool prev = copySet.EnforceConstraints;\r
533                         copySet.EnforceConstraints = false;\r
534 \r
535                         Hashtable addedRows = new Hashtable ();\r
536 \r
537                         for (int i = 0; i < Tables.Count; i++) {\r
538                                 DataTable origTable = Tables [i];\r
539                                 DataTable copyTable = copySet.Tables[origTable.TableName];\r
540                                 for (int j = 0; j < origTable.Rows.Count; j++) {\r
541                                         DataRow row = origTable.Rows [j];\r
542                                         if (!row.IsRowChanged (rowStates) || addedRows.Contains (row))\r
543                                                 continue;\r
544                                         AddChangedRow (addedRows, copyTable, row);\r
545                                 }\r
546                         }\r
547                         copySet.EnforceConstraints = prev;\r
548                         return copySet;\r
549                 }\r
550 \r
551                 private void AddChangedRow (Hashtable addedRows, DataTable copyTable, DataRow row)\r
552                 {\r
553                         if (addedRows.ContainsKey (row))\r
554                                 return;\r
555 \r
556                         foreach (DataRelation relation in row.Table.ParentRelations) {\r
557                                 DataRow parent = ( row.RowState != DataRowState.Deleted ?\r
558                                                    row.GetParentRow (relation) :\r
559                                                    row.GetParentRow (relation, DataRowVersion.Original)\r
560                                                    );\r
561                                 if (parent == null)\r
562                                         continue;\r
563                                 // add the parent row\r
564                                 DataTable parentCopyTable = copyTable.DataSet.Tables [parent.Table.TableName];\r
565                                 AddChangedRow (addedRows, parentCopyTable, parent);\r
566                         }\r
567 \r
568                         // add the current row\r
569                         DataRow newRow = copyTable.NewNotInitializedRow ();\r
570                         copyTable.Rows.AddInternal (newRow);\r
571                         // Don't check for ReadOnly, when cloning data to new uninitialized row.\r
572                         row.CopyValuesToRow (newRow, false);\r
573                         newRow.XmlRowID = row.XmlRowID;\r
574                         addedRows.Add (row, row);\r
575                 }\r
576 \r
577                 public string GetXml ()\r
578                 {\r
579                         StringWriter Writer = new StringWriter ();\r
580                         WriteXml (Writer, XmlWriteMode.IgnoreSchema);\r
581                         return Writer.ToString ();\r
582                 }\r
583 \r
584                 public string GetXmlSchema ()\r
585                 {\r
586                         StringWriter Writer = new StringWriter ();\r
587                         WriteXmlSchema (Writer);\r
588                         return Writer.ToString ();\r
589                 }\r
590 \r
591                 public bool HasChanges ()\r
592                 {\r
593                         return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
594                 }\r
595 \r
596                 public bool HasChanges (DataRowState rowStates)\r
597                 {\r
598                         if (((int) rowStates & 0xffffffe0) != 0)\r
599                                 throw new ArgumentOutOfRangeException ("rowStates");\r
600 \r
601                         DataTableCollection tableCollection = Tables;\r
602                         DataTable table;\r
603                         DataRowCollection rowCollection;\r
604                         DataRow row;\r
605 \r
606                         for (int i = 0; i < tableCollection.Count; i++) {\r
607                                 table = tableCollection [i];\r
608                                 rowCollection = table.Rows;\r
609                                 for (int j = 0; j < rowCollection.Count; j++) {\r
610                                         row = rowCollection [j];\r
611                                         if ((row.RowState & rowStates) != 0)\r
612                                                 return true;\r
613                                 }\r
614                         }\r
615 \r
616                         return false;\r
617                 }\r
618 \r
619                 public void InferXmlSchema (XmlReader reader, string[] nsArray)\r
620                 {\r
621                         if (reader == null)\r
622                                 return;\r
623                         XmlDocument doc = new XmlDocument ();\r
624                         doc.Load (reader);\r
625                         InferXmlSchema (doc, nsArray);\r
626                 }\r
627 \r
628                 private void InferXmlSchema (XmlDocument doc, string [] nsArray)\r
629                 {\r
630                         XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);\r
631                 }\r
632 \r
633                 public void InferXmlSchema (Stream stream, string[] nsArray)\r
634                 {\r
635                         InferXmlSchema (new XmlTextReader (stream), nsArray);\r
636                 }\r
637 \r
638                 public void InferXmlSchema (TextReader reader, string[] nsArray)\r
639                 {\r
640                         InferXmlSchema (new XmlTextReader (reader), nsArray);\r
641                 }\r
642 \r
643                 public void InferXmlSchema (string fileName, string[] nsArray)\r
644                 {\r
645                         XmlTextReader reader = new XmlTextReader (fileName);\r
646                         try {\r
647                                 InferXmlSchema (reader, nsArray);\r
648                         } finally {\r
649                                 reader.Close ();\r
650                         }\r
651                 }\r
652 \r
653                 public virtual void RejectChanges ()\r
654                 {\r
655                         int i;\r
656                         bool oldEnforceConstraints = this.EnforceConstraints;\r
657                         this.EnforceConstraints = false;\r
658 \r
659                         for (i = 0; i < this.Tables.Count;i++)\r
660                                 this.Tables[i].RejectChanges ();\r
661 \r
662                         this.EnforceConstraints = oldEnforceConstraints;\r
663                 }\r
664 \r
665                 public virtual void Reset ()\r
666                 {\r
667                         // first we remove all ForeignKeyConstraints (if we will not do that\r
668                         // we will get an exception when clearing the tables).\r
669                         for (int i = 0; i < Tables.Count; i++) {\r
670                                 ConstraintCollection cc = Tables[i].Constraints;\r
671                                 for (int j = 0; j < cc.Count; j++) {\r
672                                         if (cc[j] is ForeignKeyConstraint)\r
673                                                 cc.Remove (cc[j]);\r
674                                 }\r
675                         }\r
676 \r
677                         Clear ();\r
678                         Relations.Clear ();\r
679                         Tables.Clear ();\r
680                 }\r
681 \r
682                 public void WriteXml (Stream stream)\r
683                 {\r
684                         XmlTextWriter writer = new XmlTextWriter (stream, null);\r
685                         writer.Formatting = Formatting.Indented;\r
686                         WriteXml (writer);\r
687                 }\r
688 \r
689                 ///<summary>\r
690                 /// Writes the current data for the DataSet to the specified file.\r
691                 /// </summary>\r
692                 /// <param name="filename">Fully qualified filename to write to</param>\r
693                 public void WriteXml (string fileName)\r
694                 {\r
695                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
696                         writer.Formatting = Formatting.Indented;\r
697                         writer.WriteStartDocument (true);\r
698                         try {\r
699                                 WriteXml (writer);\r
700                         } finally {\r
701                                 writer.WriteEndDocument ();\r
702                                 writer.Close ();\r
703                         }\r
704                 }\r
705 \r
706                 public void WriteXml (TextWriter writer)\r
707                 {\r
708                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
709                         xwriter.Formatting = Formatting.Indented;\r
710                         WriteXml (xwriter);\r
711                 }\r
712 \r
713                 public void WriteXml (XmlWriter writer)\r
714                 {\r
715                         WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
716                 }\r
717 \r
718                 public void WriteXml (string fileName, XmlWriteMode mode)\r
719                 {\r
720                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
721                         writer.Formatting = Formatting.Indented;\r
722                         writer.WriteStartDocument (true);\r
723 \r
724                         try {\r
725                                 WriteXml (writer, mode);\r
726                         } finally {\r
727                                 writer.WriteEndDocument ();\r
728                                 writer.Close ();\r
729                         }\r
730                 }\r
731 \r
732                 public void WriteXml (Stream stream, XmlWriteMode mode)\r
733                 {\r
734                         XmlTextWriter writer = new XmlTextWriter (stream, null);\r
735                         writer.Formatting = Formatting.Indented;\r
736                         WriteXml (writer, mode);\r
737                 }\r
738 \r
739                 public void WriteXml (TextWriter writer, XmlWriteMode mode)\r
740                 {\r
741                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
742                         xwriter.Formatting = Formatting.Indented;\r
743                         WriteXml (xwriter, mode);\r
744                 }\r
745 \r
746                 public void WriteXml (XmlWriter writer, XmlWriteMode mode)\r
747                 {\r
748                         if (mode == XmlWriteMode.DiffGram) {\r
749                                 SetRowsID();\r
750                                 WriteDiffGramElement(writer);\r
751                         }\r
752 \r
753                         // It should not write when there is no content to be written\r
754                         bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);\r
755                         for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)\r
756                                 shouldOutputContent = tableCollection [n].Rows.Count > 0;\r
757 \r
758                         if (shouldOutputContent) {\r
759                                 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));\r
760 \r
761                                 if (mode == XmlWriteMode.WriteSchema)\r
762                                         DoWriteXmlSchema (writer);\r
763 \r
764                                 WriteTables (writer, mode, Tables, DataRowVersion.Default);\r
765                                 writer.WriteEndElement ();\r
766                         }\r
767 \r
768                         if (mode == XmlWriteMode.DiffGram) {\r
769                                 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {\r
770                                         DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);\r
771                                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
772                                         WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);\r
773                                         writer.WriteEndElement ();\r
774                                 }\r
775                         }\r
776 \r
777                         if (mode == XmlWriteMode.DiffGram)\r
778                                 writer.WriteEndElement (); // diffgr:diffgram\r
779 \r
780                         writer.Flush ();\r
781                 }\r
782 \r
783                 public void WriteXmlSchema (Stream stream)\r
784                 {\r
785                         XmlTextWriter writer = new XmlTextWriter (stream, null );\r
786                         writer.Formatting = Formatting.Indented;\r
787                         WriteXmlSchema (writer);\r
788                 }\r
789 \r
790                 public void WriteXmlSchema (string fileName)\r
791                 {\r
792                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
793                         try {\r
794                                 writer.Formatting = Formatting.Indented;\r
795                                 writer.WriteStartDocument (true);\r
796                                 WriteXmlSchema (writer);\r
797                         } finally {\r
798                                 writer.WriteEndDocument ();\r
799                                 writer.Close ();\r
800                         }\r
801                 }\r
802 \r
803                 public void WriteXmlSchema (TextWriter writer)\r
804                 {\r
805                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
806                         try {\r
807                                 xwriter.Formatting = Formatting.Indented;\r
808                                 WriteXmlSchema (xwriter);\r
809                         } finally {\r
810                                 xwriter.Close ();\r
811                         }\r
812                 }\r
813 \r
814                 public void WriteXmlSchema (XmlWriter writer)\r
815                 {\r
816                         //Create a skeleton doc and then write the schema\r
817                         //proper which is common to the WriteXml method in schema mode\r
818                         DoWriteXmlSchema (writer);\r
819                 }\r
820 \r
821                 public void ReadXmlSchema (Stream stream)\r
822                 {\r
823                         XmlReader reader = new XmlTextReader (stream, null);\r
824                         ReadXmlSchema (reader);\r
825                 }\r
826 \r
827                 public void ReadXmlSchema (string fileName)\r
828                 {\r
829                         XmlReader reader = new XmlTextReader (fileName);\r
830                         try {\r
831                                 ReadXmlSchema (reader);\r
832                         } finally {\r
833                                 reader.Close ();\r
834                         }\r
835                 }\r
836 \r
837                 public void ReadXmlSchema (TextReader reader)\r
838                 {\r
839                         XmlReader xr = new XmlTextReader (reader);\r
840                         ReadXmlSchema (xr);\r
841                 }\r
842 \r
843                 public void ReadXmlSchema (XmlReader reader)\r
844                 {\r
845 #if true\r
846                         XmlSchemaDataImporter xsdImporter = new XmlSchemaDataImporter (this, reader, true);\r
847                         xsdImporter.Process ();\r
848 #if NET_2_0\r
849                         tableAdapterSchemaInfo = xsdImporter.CurrentAdapter;\r
850 #endif\r
851 #else\r
852                         XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);\r
853                         SchemaMapper.Read (reader);\r
854 #endif\r
855                 }\r
856 \r
857                 public XmlReadMode ReadXml (Stream stream)\r
858                 {\r
859                         return ReadXml (new XmlTextReader (stream));\r
860                 }\r
861 \r
862                 public XmlReadMode ReadXml (string fileName)\r
863                 {\r
864                         XmlTextReader reader = new XmlTextReader (fileName);\r
865                         try {\r
866                                 return ReadXml (reader);\r
867                         } finally {\r
868                                 reader.Close ();\r
869                         }\r
870                 }\r
871 \r
872                 public XmlReadMode ReadXml (TextReader reader)\r
873                 {\r
874                         return ReadXml (new XmlTextReader (reader));\r
875                 }\r
876 \r
877                 public XmlReadMode ReadXml (XmlReader reader)\r
878                 {\r
879                         return ReadXml (reader, XmlReadMode.Auto);\r
880                 }\r
881 \r
882                 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)\r
883                 {\r
884                         return ReadXml (new XmlTextReader (stream), mode);\r
885                 }\r
886 \r
887                 public XmlReadMode ReadXml (string fileName, XmlReadMode mode)\r
888                 {\r
889                         XmlTextReader reader = new XmlTextReader (fileName);\r
890                         try {\r
891                                 return ReadXml (reader, mode);\r
892                         } finally {\r
893                                 reader.Close ();\r
894                         }\r
895                 }\r
896 \r
897                 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)\r
898                 {\r
899                         return ReadXml (new XmlTextReader (reader), mode);\r
900                 }\r
901 \r
902                 // LAMESPEC: XmlReadMode.Fragment is far from presisely\r
903                 // documented. MS.NET infers schema against this mode.\r
904                 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)\r
905                 {\r
906                         if (reader == null)\r
907                                 return mode;\r
908 \r
909                         switch (reader.ReadState) {\r
910                         case ReadState.EndOfFile:\r
911                         case ReadState.Error:\r
912                         case ReadState.Closed:\r
913                                 return mode;\r
914                         }\r
915                         // Skip XML declaration and prolog\r
916                         reader.MoveToContent ();\r
917                         if (reader.EOF)\r
918                                 return mode;\r
919 \r
920                         if (reader is XmlTextReader) {\r
921                                 // we dont need whitespace\r
922                                 ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.None;\r
923                         }\r
924 \r
925                         XmlDiffLoader DiffLoader = null;\r
926 \r
927                         // If diffgram, then read the first element as diffgram\r
928                         if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {\r
929                                 switch (mode) {\r
930                                         case XmlReadMode.Auto:\r
931                                         case XmlReadMode.DiffGram:\r
932                                                 if (DiffLoader == null)\r
933                                                         DiffLoader = new XmlDiffLoader (this);\r
934                                                 DiffLoader.Load (reader);\r
935                                                 // (and leave rest of the reader as is)\r
936                                                 return XmlReadMode.DiffGram;\r
937                                         case XmlReadMode.Fragment:\r
938                                                 reader.Skip ();\r
939                                                 // (and continue to read)\r
940                                                 break;\r
941                                         default:\r
942                                                 reader.Skip ();\r
943                                                 // (and leave rest of the reader as is)\r
944                                                 return mode;\r
945                                 }\r
946                         }\r
947 \r
948                         // If schema, then read the first element as schema\r
949                         if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
950                                 switch (mode) {\r
951                                         case XmlReadMode.IgnoreSchema:\r
952                                         case XmlReadMode.InferSchema:\r
953                                                 reader.Skip ();\r
954                                                 // (and break up read)\r
955                                                 return mode;\r
956                                         case XmlReadMode.Fragment:\r
957                                                 ReadXmlSchema (reader);\r
958                                                 // (and continue to read)\r
959                                                 break;\r
960                                         case XmlReadMode.Auto:\r
961                                                 if (Tables.Count == 0) {\r
962                                                         ReadXmlSchema (reader);\r
963                                                         return XmlReadMode.ReadSchema;\r
964                                                 } else {\r
965                                                         // otherwise just ignore and return IgnoreSchema\r
966                                                         reader.Skip ();\r
967                                                         return XmlReadMode.IgnoreSchema;\r
968                                                 }\r
969                                         default:\r
970                                                 ReadXmlSchema (reader);\r
971                                                 // (and leave rest of the reader as is)\r
972                                                 return mode; // When DiffGram, return DiffGram\r
973                                 }\r
974                         }\r
975 \r
976                         if (reader.EOF)\r
977                                 return mode;\r
978 \r
979                         int depth = (reader.NodeType == XmlNodeType.Element) ? reader.Depth : -1;\r
980 \r
981                         XmlDocument doc = new XmlDocument ();\r
982                         XmlElement root = doc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);\r
983                         if (reader.HasAttributes) {\r
984                                 for (int i = 0; i < reader.AttributeCount; i++) {\r
985                                         reader.MoveToAttribute(i);\r
986                                         if (reader.NamespaceURI == XmlConstants.XmlnsNS)\r
987                                                 root.SetAttribute(reader.Name, reader.GetAttribute(i));\r
988                                         else {\r
989                                                 XmlAttribute attr = root.SetAttributeNode(reader.LocalName, reader.NamespaceURI);\r
990                                                 attr.Prefix = reader.Prefix;\r
991                                                 attr.Value = reader.GetAttribute(i);\r
992                                         }\r
993                                 }\r
994                         }\r
995 \r
996                         reader.Read();\r
997                         XmlReadMode retMode = mode;\r
998                         bool schemaLoaded = false;\r
999 \r
1000                         for (;;) {\r
1001                                 if( reader.Depth == depth ||\r
1002                                         reader.NodeType == XmlNodeType.EndElement)\r
1003                                         break;\r
1004 \r
1005                                 if (reader.NodeType != XmlNodeType.Element) {\r
1006                                         if (!reader.Read())\r
1007                                                 break;\r
1008                                         continue;\r
1009                                 }\r
1010 \r
1011                                 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
1012                                         switch (mode) {\r
1013                                                 case XmlReadMode.IgnoreSchema:\r
1014                                                 case XmlReadMode.InferSchema:\r
1015                                                         reader.Skip ();\r
1016                                                         break;\r
1017 \r
1018                                                 default:\r
1019                                                         ReadXmlSchema (reader);\r
1020                                                         retMode = XmlReadMode.ReadSchema;\r
1021                                                         schemaLoaded = true;\r
1022                                                         // (and leave rest of the reader as is)\r
1023                                                         break;\r
1024                                         }\r
1025 \r
1026                                         continue;\r
1027                                 }\r
1028 \r
1029                                 if ((reader.LocalName == "diffgram") && (reader.NamespaceURI == XmlConstants.DiffgrNamespace)) {\r
1030                                         if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)\r
1031                                                 || mode == XmlReadMode.Auto) {\r
1032                                                 if (DiffLoader == null)\r
1033                                                         DiffLoader = new XmlDiffLoader (this);\r
1034                                                 DiffLoader.Load (reader);\r
1035                                                 // (and leave rest of the reader as is)\r
1036                                                 retMode = XmlReadMode.DiffGram;\r
1037                                         }\r
1038                                         else\r
1039                                                 reader.Skip();\r
1040 \r
1041                                         continue;\r
1042                                 }\r
1043 \r
1044                                 //collect data\r
1045                                 XmlNode n = doc.ReadNode(reader);\r
1046                                 root.AppendChild(n);\r
1047                         }\r
1048 \r
1049                         if (reader.NodeType == XmlNodeType.EndElement)\r
1050                                 reader.Read ();\r
1051                         reader.MoveToContent();\r
1052 \r
1053                         if (mode == XmlReadMode.DiffGram) {\r
1054                                 return retMode;\r
1055                         }\r
1056 \r
1057                         doc.AppendChild(root);\r
1058 \r
1059                         if (!schemaLoaded &&\r
1060                                 retMode != XmlReadMode.ReadSchema &&\r
1061                                 mode != XmlReadMode.IgnoreSchema &&\r
1062                                 mode != XmlReadMode.Fragment &&\r
1063                                 (Tables.Count == 0 || mode == XmlReadMode.InferSchema)) {\r
1064                                 InferXmlSchema(doc, null);\r
1065                                 if (mode == XmlReadMode.Auto)\r
1066                                         retMode = XmlReadMode.InferSchema;\r
1067                         }\r
1068 \r
1069                         reader = new XmlNodeReader (doc);\r
1070                         XmlDataReader.ReadXml (this, reader, mode);\r
1071 \r
1072                         return retMode == XmlReadMode.Auto ?\r
1073                                 XmlReadMode.IgnoreSchema : retMode;\r
1074                 }\r
1075                 #endregion // Public Methods\r
1076 \r
1077                 #region Public Events\r
1078 \r
1079                 [DataCategory ("Action")]\r
1080 #if !NET_2_0\r
1081                 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]\r
1082 #endif\r
1083                 public event MergeFailedEventHandler MergeFailed;\r
1084 \r
1085                 #endregion // Public Events\r
1086 \r
1087                 #region IListSource methods\r
1088                 IList IListSource.GetList ()\r
1089                 {\r
1090                         return DefaultViewManager;\r
1091                 }\r
1092 \r
1093                 bool IListSource.ContainsListCollection {\r
1094                         get {\r
1095                                 return true;\r
1096                         }\r
1097                 }\r
1098                 #endregion IListSource methods\r
1099 \r
1100                 #region ISupportInitialize methods\r
1101 \r
1102                 internal bool InitInProgress {\r
1103                         get { return initInProgress; }\r
1104                         set { initInProgress = value; }\r
1105                 }\r
1106 \r
1107                 public void BeginInit ()\r
1108                 {\r
1109                         InitInProgress = true;\r
1110 #if NET_2_0\r
1111                         dataSetInitialized = false;\r
1112 #endif\r
1113                 }\r
1114 \r
1115                 public void EndInit ()\r
1116                 {\r
1117                         // Finsh the init'ing the tables only after adding all the\r
1118                         // tables to the collection.\r
1119                         Tables.PostAddRange ();\r
1120                         for (int i=0; i < Tables.Count; ++i) {\r
1121                                 if (!Tables [i].InitInProgress)\r
1122                                         continue;\r
1123                                 Tables [i].FinishInit ();\r
1124                         }\r
1125 \r
1126                         Relations.PostAddRange ();\r
1127                         InitInProgress = false;\r
1128 #if NET_2_0\r
1129                         dataSetInitialized = true;\r
1130                         DataSetInitialized ();\r
1131 #endif\r
1132                 }\r
1133                 #endregion\r
1134 \r
1135                 #region ISerializable\r
1136 #if NET_2_0\r
1137                 public virtual\r
1138 #endif\r
1139                 void\r
1140 #if !NET_2_0\r
1141                 ISerializable.\r
1142 #endif\r
1143                 GetObjectData (SerializationInfo info, StreamingContext context)\r
1144                 {\r
1145 #if NET_2_0\r
1146                         if (RemotingFormat == SerializationFormat.Xml) {\r
1147                                 info.AddValue ("SchemaSerializationMode.DataSet", this.SchemaSerializationMode);\r
1148 #endif\r
1149                                 StringWriter sw = new StringWriter ();\r
1150                                 XmlTextWriter writer = new XmlTextWriter (sw);\r
1151                                 DoWriteXmlSchema (writer);\r
1152                                 writer.Flush ();\r
1153                                 info.AddValue ("XmlSchema", sw.ToString ());\r
1154 \r
1155                                 sw = new StringWriter ();\r
1156                                 writer = new XmlTextWriter (sw);\r
1157                                 WriteXml (writer, XmlWriteMode.DiffGram);\r
1158                                 writer.Flush ();\r
1159                                 info.AddValue ("XmlDiffGram", sw.ToString ());\r
1160 #if NET_2_0\r
1161                         } else /*if (DataSet.RemotingFormat == SerializationFormat.Binary)*/ {\r
1162                                 BinarySerialize (info);\r
1163                         }\r
1164 #endif\r
1165                 }\r
1166                 #endregion\r
1167 \r
1168                 #region Protected Methods\r
1169                 protected void GetSerializationData (SerializationInfo info, StreamingContext context)\r
1170                 {\r
1171                         string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;\r
1172                         XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
1173                         ReadXml (reader, XmlReadMode.DiffGram);\r
1174                         reader.Close ();\r
1175                 }\r
1176 \r
1177 \r
1178                 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()\r
1179                 {\r
1180                         return null;\r
1181                 }\r
1182 \r
1183                 protected virtual void ReadXmlSerializable (XmlReader reader)\r
1184                 {\r
1185                         ReadXml (reader, XmlReadMode.DiffGram);\r
1186                 }\r
1187 \r
1188                 void IXmlSerializable.ReadXml (XmlReader reader)\r
1189                 {\r
1190                         ReadXmlSerializable(reader);\r
1191                 }\r
1192 \r
1193                 void IXmlSerializable.WriteXml (XmlWriter writer)\r
1194                 {\r
1195                         DoWriteXmlSchema (writer);\r
1196                         WriteXml (writer, XmlWriteMode.DiffGram);\r
1197                 }\r
1198 \r
1199                 XmlSchema IXmlSerializable.GetSchema ()\r
1200                 {\r
1201                         if (GetType() == typeof(DataSet))\r
1202                                 return null;\r
1203                         MemoryStream stream = new MemoryStream();\r
1204                         XmlTextWriter writer = new XmlTextWriter(stream, null);\r
1205                         WriteXmlSchema(writer);\r
1206                         stream.Position = 0;\r
1207                         return XmlSchema.Read(new XmlTextReader(stream), (ValidationEventHandler)null);\r
1208                 }\r
1209 \r
1210                 protected virtual bool ShouldSerializeRelations ()\r
1211                 {\r
1212                         return true;\r
1213                 }\r
1214 \r
1215                 protected virtual bool ShouldSerializeTables ()\r
1216                 {\r
1217                         return true;\r
1218                 }\r
1219 \r
1220                 [MonoTODO]\r
1221                 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)\r
1222                 {\r
1223                         throw new NotImplementedException ();\r
1224                 }\r
1225 \r
1226                 [MonoTODO]\r
1227                 protected virtual void OnRemoveRelation (DataRelation relation)\r
1228                 {\r
1229                         throw new NotImplementedException ();\r
1230                 }\r
1231 \r
1232                 [MonoTODO]\r
1233                 protected virtual void OnRemoveTable (DataTable table)\r
1234                 {\r
1235                         throw new NotImplementedException ();\r
1236                 }\r
1237 \r
1238                 internal virtual void OnMergeFailed (MergeFailedEventArgs e)\r
1239                 {\r
1240                         if (MergeFailed != null)\r
1241                                 MergeFailed (this, e);\r
1242                         else\r
1243                                 throw new DataException (e.Conflict);\r
1244                 }\r
1245 \r
1246                 [MonoTODO]\r
1247                 protected internal void RaisePropertyChanging (string name)\r
1248                 {\r
1249                 }\r
1250 \r
1251                 #endregion\r
1252 \r
1253                 #region Private Methods\r
1254 \r
1255                 internal static string WriteObjectXml (object o)\r
1256                 {\r
1257                         switch (Type.GetTypeCode (o.GetType ())) {\r
1258                                 case TypeCode.Boolean:\r
1259                                         return XmlConvert.ToString ((Boolean) o);\r
1260                                 case TypeCode.Byte:\r
1261                                         return XmlConvert.ToString ((Byte) o);\r
1262                                 case TypeCode.Char:\r
1263                                         return XmlConvert.ToString ((Char) o);\r
1264                                 case TypeCode.DateTime:\r
1265 #if NET_2_0\r
1266                                         return XmlConvert.ToString ((DateTime) o, XmlDateTimeSerializationMode.Unspecified);\r
1267 #else\r
1268                                         return XmlConvert.ToString ((DateTime) o);\r
1269 #endif\r
1270                                 case TypeCode.Decimal:\r
1271                                         return XmlConvert.ToString ((Decimal) o);\r
1272                                 case TypeCode.Double:\r
1273                                         return XmlConvert.ToString ((Double) o);\r
1274                                 case TypeCode.Int16:\r
1275                                         return XmlConvert.ToString ((Int16) o);\r
1276                                 case TypeCode.Int32:\r
1277                                         return XmlConvert.ToString ((Int32) o);\r
1278                                 case TypeCode.Int64:\r
1279                                         return XmlConvert.ToString ((Int64) o);\r
1280                                 case TypeCode.SByte:\r
1281                                         return XmlConvert.ToString ((SByte) o);\r
1282                                 case TypeCode.Single:\r
1283                                         return XmlConvert.ToString ((Single) o);\r
1284                                 case TypeCode.UInt16:\r
1285                                         return XmlConvert.ToString ((UInt16) o);\r
1286                                 case TypeCode.UInt32:\r
1287                                         return XmlConvert.ToString ((UInt32) o);\r
1288                                 case TypeCode.UInt64:\r
1289                                         return XmlConvert.ToString ((UInt64) o);\r
1290                         }\r
1291                         if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);\r
1292                         if (o is Guid) return XmlConvert.ToString ((Guid) o);\r
1293                         if (o is byte[]) return Convert.ToBase64String ((byte[])o);\r
1294 \r
1295                         return o.ToString ();\r
1296                 }\r
1297 \r
1298                 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)\r
1299                 {\r
1300                         //WriteTable takes care of skipping a table if it has a\r
1301                         //Nested Parent Relationship\r
1302                         foreach (DataTable table in tableCollection)\r
1303                                 WriteTable ( writer, table, mode, version);\r
1304                 }\r
1305 \r
1306                 internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)\r
1307                 {\r
1308                         DataRow[] rows = table.NewRowArray(table.Rows.Count);\r
1309                         table.Rows.CopyTo (rows, 0);\r
1310                         WriteTable (writer, rows, mode, version, true);\r
1311                 }\r
1312 \r
1313                 internal static void WriteTable (XmlWriter writer,\r
1314                         DataRow [] rows,\r
1315                         XmlWriteMode mode,\r
1316                         DataRowVersion version, bool skipIfNested)\r
1317                 {\r
1318                         if (rows.Length == 0) return;\r
1319                         DataTable table = rows[0].Table;\r
1320 \r
1321                         if (table.TableName == null || table.TableName == "")\r
1322                                 throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");\r
1323 \r
1324                         //The columns can be attributes, hidden, elements, or simple content\r
1325                         //There can be 0-1 simple content cols or 0-* elements\r
1326                         System.Collections.ArrayList atts;\r
1327                         System.Collections.ArrayList elements;\r
1328                         DataColumn simple = null;\r
1329 \r
1330                         SplitColumns (table, out atts, out elements, out simple);\r
1331                         //sort out the namespacing\r
1332 \r
1333                         foreach (DataRow row in rows) {\r
1334                                 if (skipIfNested) {\r
1335                                         // Skip rows that is a child of any tables.\r
1336                                         bool skip = false;\r
1337                                         for (int i = 0; i < table.ParentRelations.Count; i++) {\r
1338                                                 DataRelation prel = table.ParentRelations [i];\r
1339                                                 if (!prel.Nested)\r
1340                                                         continue;\r
1341                                                 if (row.GetParentRow (prel) != null) {\r
1342                                                         skip = true;\r
1343                                                         continue;\r
1344                                                 }\r
1345                                         }\r
1346                                         if (skip)\r
1347                                                 continue;\r
1348                                 }\r
1349 \r
1350                                 if (!row.HasVersion(version) ||\r
1351                                    (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged\r
1352                                       && version == DataRowVersion.Original))\r
1353                                         continue;\r
1354 \r
1355                                 // First check are all the rows null. If they are we just write empty element\r
1356                                 bool AllNulls = true;\r
1357                                 foreach (DataColumn dc in table.Columns) {\r
1358                                         if (row [dc.ColumnName, version] != DBNull.Value) {\r
1359                                                 AllNulls = false;\r
1360                                                 break;\r
1361                                         }\r
1362                                 }\r
1363 \r
1364                                 // If all of the columns were null, we have to write empty element\r
1365                                 if (AllNulls) {\r
1366                                         writer.WriteElementString (XmlHelper.Encode (table.TableName), "");\r
1367                                         continue;\r
1368                                 }\r
1369 \r
1370                                 WriteTableElement (writer, mode, table, row, version);\r
1371 \r
1372                                 foreach (DataColumn col in atts)\r
1373                                         WriteColumnAsAttribute (writer, mode, col, row, version);\r
1374 \r
1375                                 if (simple != null) {\r
1376                                         writer.WriteString (WriteObjectXml (row[simple, version]));\r
1377                                 } else {\r
1378                                         foreach (DataColumn col in elements)\r
1379                                                 WriteColumnAsElement (writer, mode, col, row, version);\r
1380                                 }\r
1381 \r
1382                                 foreach (DataRelation relation in table.ChildRelations) {\r
1383                                         if (relation.Nested)\r
1384                                                 WriteTable (writer, row.GetChildRows (relation), mode, version, false);\r
1385                                 }\r
1386 \r
1387                                 writer.WriteEndElement ();\r
1388                         }\r
1389 \r
1390                 }\r
1391 \r
1392                 internal static void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)\r
1393                 {\r
1394                         string colnspc = null;\r
1395                         object rowObject = row [col, version];\r
1396 \r
1397                         if (rowObject == null || rowObject == DBNull.Value)\r
1398                                 return;\r
1399 \r
1400                         if (col.Namespace != String.Empty)\r
1401                                 colnspc = col.Namespace;\r
1402 \r
1403                         //TODO check if I can get away with write element string\r
1404                         WriteStartElement (writer, mode, colnspc, col.Prefix, XmlHelper.Encode (col.ColumnName));       \r
1405                         if (typeof (IXmlSerializable).IsAssignableFrom (col.DataType) \r
1406                             || col.DataType == typeof (object)) {\r
1407                                 IXmlSerializable serializableObj = rowObject as IXmlSerializable;\r
1408                                 if (serializableObj == null)\r
1409                                         throw new InvalidOperationException ();\r
1410                                 ((IXmlSerializable)rowObject).WriteXml (writer);                                \r
1411                         } else {\r
1412                                 writer.WriteString (WriteObjectXml (rowObject));\r
1413                         }\r
1414 \r
1415                         writer.WriteEndElement ();\r
1416                 }\r
1417 \r
1418                 internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)\r
1419                 {\r
1420                         if (!row.IsNull (col))\r
1421                                 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));\r
1422                 }\r
1423 \r
1424                 internal static void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)\r
1425                 {\r
1426                         //sort out the namespacing\r
1427                         string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;\r
1428 \r
1429                         WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));\r
1430 \r
1431                         if (mode == XmlWriteMode.DiffGram) {\r
1432                                 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));\r
1433                                 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));\r
1434                                 string modeName = null;\r
1435                                 if (row.RowState == DataRowState.Modified)\r
1436                                         modeName = "modified";\r
1437                                 else if (row.RowState == DataRowState.Added)\r
1438                                         modeName = "inserted";\r
1439 \r
1440                                 if (version != DataRowVersion.Original && modeName != null)\r
1441                                         WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);\r
1442                         }\r
1443                 }\r
1444 \r
1445                 internal static void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)\r
1446                 {\r
1447                         writer.WriteStartElement (prefix, name, nspc);\r
1448                 }\r
1449 \r
1450                 internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)\r
1451                 {\r
1452                         switch ( mode) {\r
1453                         //      case XmlWriteMode.WriteSchema:\r
1454                         //              writer.WriteAttributeString (prefix, name, nspc);\r
1455                         //              break;\r
1456                                 case XmlWriteMode.DiffGram:\r
1457                                         writer.WriteAttributeString (prefix, name, nspc,stringValue);\r
1458                                         break;\r
1459                                 default:\r
1460                                         writer.WriteAttributeString (name, stringValue);\r
1461                                         break;\r
1462                         };\r
1463                 }\r
1464 \r
1465                 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)\r
1466                 {\r
1467                         if (mode == XmlWriteMode.DiffGram) {\r
1468                                 table.SetRowsID ();\r
1469                                 WriteDiffGramElement (writer);\r
1470                         }\r
1471 \r
1472                         WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));\r
1473 \r
1474                         WriteTable (writer, table, mode, DataRowVersion.Default);\r
1475 \r
1476                         if (mode == XmlWriteMode.DiffGram) {\r
1477                                 writer.WriteEndElement (); //DataSet name\r
1478                                 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {\r
1479 \r
1480                                         DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);\r
1481                                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
1482                                         WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);\r
1483                                         writer.WriteEndElement ();\r
1484                                 }\r
1485                         }\r
1486                         writer.WriteEndElement (); // DataSet name or diffgr:diffgram\r
1487                 }\r
1488 \r
1489                 private void DoWriteXmlSchema (XmlWriter writer)\r
1490                 {\r
1491                         if (writer.WriteState == WriteState.Start)\r
1492                                 writer.WriteStartDocument ();\r
1493                         XmlSchemaWriter.WriteXmlSchema (this, writer);\r
1494                 }\r
1495 \r
1496                 ///<summary>\r
1497                 /// Helper function to split columns into attributes elements and simple\r
1498                 /// content\r
1499                 /// </summary>\r
1500                 internal static void SplitColumns (DataTable table,\r
1501                         out ArrayList atts,\r
1502                         out ArrayList elements,\r
1503                         out DataColumn simple)\r
1504                 {\r
1505                         //The columns can be attributes, hidden, elements, or simple content\r
1506                         //There can be 0-1 simple content cols or 0-* elements\r
1507                         atts = new System.Collections.ArrayList ();\r
1508                         elements = new System.Collections.ArrayList ();\r
1509                         simple = null;\r
1510 \r
1511                         //Sort out the columns\r
1512                         foreach (DataColumn col in table.Columns) {\r
1513                                 switch (col.ColumnMapping) {\r
1514                                         case MappingType.Attribute:\r
1515                                                 atts.Add (col);\r
1516                                                 break;\r
1517                                         case MappingType.Element:\r
1518                                                 elements.Add (col);\r
1519                                                 break;\r
1520                                         case MappingType.SimpleContent:\r
1521                                                 if (simple != null) {\r
1522                                                         throw new System.InvalidOperationException ("There may only be one simple content element");\r
1523                                                 }\r
1524                                                 simple = col;\r
1525                                                 break;\r
1526                                         default:\r
1527                                                 //ignore Hidden elements\r
1528                                                 break;\r
1529                                 }\r
1530                         }\r
1531                 }\r
1532 \r
1533                 internal static void WriteDiffGramElement (XmlWriter writer)\r
1534                 {\r
1535                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");\r
1536                         WriteAttributeString (writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);\r
1537                 }\r
1538 \r
1539                 private void SetRowsID ()\r
1540                 {\r
1541                         foreach (DataTable table in Tables)\r
1542                                 table.SetRowsID ();\r
1543                 }\r
1544 \r
1545                 #endregion //Private Xml Serialisation\r
1546         }\r
1547 \r
1548 #if NET_2_0\r
1549         [XmlSchemaProvider ("GetDataSetSchema")]\r
1550         [XmlRoot ("DataSet")]\r
1551         partial class DataSet : ISupportInitializeNotification {\r
1552                 private bool dataSetInitialized = true;\r
1553                 public event EventHandler Initialized;\r
1554 \r
1555                 protected DataSet (SerializationInfo info, StreamingContext context, bool constructSchema)\r
1556                         : this ()\r
1557                 {\r
1558                         if (DetermineSchemaSerializationMode (info, context) == SchemaSerializationMode.ExcludeSchema) {\r
1559                                 InitializeDerivedDataSet ();\r
1560                         }\r
1561                         \r
1562                         if (IsBinarySerialized (info, context)) {\r
1563                                 BinaryDeserialize (info);\r
1564                                 return;\r
1565                         }\r
1566                         \r
1567                         if (constructSchema) {\r
1568                                 string s = info.GetValue ("XmlSchema", typeof (String)) as String;\r
1569                                 XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
1570                                 ReadXmlSchema (reader);\r
1571                                 reader.Close ();\r
1572                                 \r
1573                                 GetSerializationData (info, context);\r
1574                         }\r
1575                 }\r
1576 \r
1577                 SerializationFormat remotingFormat = SerializationFormat.Xml;\r
1578                 [DefaultValue (SerializationFormat.Xml)]\r
1579                 public SerializationFormat RemotingFormat {\r
1580                         get { return remotingFormat; }\r
1581                         set { remotingFormat = value; }\r
1582                 }\r
1583 \r
1584                 [Browsable (false)]\r
1585                 public bool IsInitialized {\r
1586                         get { return dataSetInitialized; }\r
1587                 }\r
1588 \r
1589                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
1590                 [Browsable (false)]\r
1591                 public virtual SchemaSerializationMode SchemaSerializationMode {\r
1592                         get { return SchemaSerializationMode.IncludeSchema; }\r
1593                         set {\r
1594                                 if (value != SchemaSerializationMode.IncludeSchema)\r
1595                                         throw new InvalidOperationException (\r
1596                                                         "Only IncludeSchema Mode can be set for Untyped DataSet");\r
1597                         }\r
1598                 }\r
1599 \r
1600                 public DataTableReader CreateDataReader (params DataTable[] dataTables)\r
1601                 {\r
1602                         return new DataTableReader (dataTables);\r
1603                 }\r
1604 \r
1605                 public DataTableReader CreateDataReader ()\r
1606                 {\r
1607                         return new DataTableReader ((DataTable[])Tables.ToArray (typeof (DataTable)));\r
1608                 }\r
1609 \r
1610                 public static XmlSchemaComplexType GetDataSetSchema (XmlSchemaSet schemaSet)\r
1611                 {\r
1612                         return new XmlSchemaComplexType ();\r
1613                 }\r
1614 \r
1615                 public void Load (IDataReader reader, LoadOption loadOption, params DataTable[] tables)\r
1616                 {\r
1617                         if (reader == null)\r
1618                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1619 \r
1620                         foreach (DataTable dt in tables) {\r
1621                                 if (dt.DataSet == null || dt.DataSet != this)\r
1622                                         throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");\r
1623                                 dt.Load (reader, loadOption);\r
1624                                 reader.NextResult ();\r
1625                         }\r
1626                 }\r
1627 \r
1628                 public void Load (IDataReader reader, LoadOption loadOption, params string[] tables)\r
1629                 {\r
1630                         if (reader == null)\r
1631                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1632 \r
1633                         foreach (string tableName in tables) {\r
1634                                 DataTable dt = Tables [tableName];\r
1635 \r
1636                                 if (dt == null) {\r
1637                                         dt = new DataTable (tableName);\r
1638                                         Tables.Add (dt);\r
1639                                 }\r
1640                                 dt.Load (reader, loadOption);\r
1641                                 reader.NextResult ();\r
1642                         }\r
1643                 }\r
1644 \r
1645                 public virtual void Load (IDataReader reader, LoadOption loadOption,\r
1646                                           FillErrorEventHandler errorHandler, params DataTable[] tables)\r
1647                 {\r
1648                         if (reader == null)\r
1649                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1650 \r
1651                         foreach (DataTable dt in tables) {\r
1652                                 if (dt.DataSet == null || dt.DataSet != this)\r
1653                                         throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");\r
1654                                 dt.Load (reader, loadOption, errorHandler);\r
1655                                 reader.NextResult ();\r
1656                         }\r
1657                 }\r
1658 \r
1659                 void BinarySerialize (SerializationInfo si)\r
1660                 {\r
1661                         Version vr = new Version(2, 0);\r
1662                         si.AddValue ("DataSet.RemotingVersion", vr, typeof (Version));\r
1663                         si.AddValue ("DataSet.RemotingFormat", RemotingFormat, typeof (SerializationFormat));\r
1664                         si.AddValue ("DataSet.DataSetName", DataSetName);\r
1665                         si.AddValue ("DataSet.Namespace", Namespace);\r
1666                         si.AddValue ("DataSet.Prefix", Prefix);\r
1667                         si.AddValue ("DataSet.CaseSensitive", CaseSensitive);\r
1668                         si.AddValue ("DataSet.LocaleLCID", Locale.LCID);\r
1669                         si.AddValue ("DataSet.EnforceConstraints", EnforceConstraints);\r
1670                         si.AddValue ("DataSet.ExtendedProperties", properties, typeof (PropertyCollection));\r
1671 \r
1672                         Tables.BinarySerialize_Schema (si);\r
1673                         Tables.BinarySerialize_Data (si);\r
1674 \r
1675                         Relations.BinarySerialize (si);\r
1676                 }\r
1677 \r
1678                 void BinaryDeserialize (SerializationInfo info)\r
1679                 {\r
1680                         ArrayList arrayList = null;\r
1681 \r
1682                         DataSetName = info.GetString ("DataSet.DataSetName");\r
1683                         Namespace = info.GetString ("DataSet.Namespace");\r
1684                         CaseSensitive = info.GetBoolean ("DataSet.CaseSensitive");\r
1685                         Locale = new CultureInfo (info.GetInt32 ("DataSet.LocaleLCID"));\r
1686                         EnforceConstraints = info.GetBoolean ("DataSet.EnforceConstraints");\r
1687                         Prefix = info.GetString ("DataSet.Prefix");\r
1688                         /*\r
1689                           FIXME: Private variable available in SerializationInfo\r
1690                           this.RemotingVersion = (System.Version) info.GetValue("DataSet.RemotingVersion",\r
1691                           typeof(System.Version));\r
1692                         */\r
1693                         properties = (PropertyCollection) info.GetValue ("DataSet.ExtendedProperties",\r
1694                                                                          typeof (PropertyCollection));\r
1695                         int tableCount = info.GetInt32 ("DataSet.Tables.Count");\r
1696 \r
1697                         Byte [] bytes;\r
1698                         DataTable dt = null;\r
1699                         for (int i = 0; i < tableCount; i++) {\r
1700                                 bytes = (Byte []) info.GetValue ("DataSet.Tables_" + i,\r
1701                                                                  typeof (Byte[]));\r
1702                                 MemoryStream ms = new MemoryStream (bytes);\r
1703                                 BinaryFormatter bf = new BinaryFormatter ();\r
1704                                 dt = (DataTable) bf.Deserialize (ms);\r
1705                                 ms.Close ();\r
1706                                 for (int j = 0; j < dt.Columns.Count; j++) {\r
1707                                         dt.Columns[j].Expression = info.GetString ("DataTable_" + i +\r
1708                                                                                    ".DataColumn_" + j +\r
1709                                                                                    ".Expression");\r
1710                                 }\r
1711                                 /*\r
1712                                   Not using\r
1713                                   int rowsCount = info.GetInt32 ("DataTable_" + i + ".Rows.Count");\r
1714                                   int recordsCount = info.GetInt32 ("DataTable_" + i + ".Records.Count");\r
1715                                 */\r
1716                                 ArrayList nullBits = (ArrayList) info.GetValue ("DataTable_" + i + ".NullBits",\r
1717                                                                                 typeof (ArrayList));\r
1718                                 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Records",\r
1719                                                                        typeof (ArrayList));\r
1720                                 BitArray rowStateBitArray = (BitArray) info.GetValue ("DataTable_" + i + ".RowStates",\r
1721                                                                                       typeof (BitArray));\r
1722                                 dt.DeserializeRecords (arrayList, nullBits, rowStateBitArray);\r
1723                                 Tables.Add (dt);\r
1724                         }\r
1725                         for (int i = 0; i < tableCount; i++) {\r
1726                                 dt = Tables [i];\r
1727                                 dt.dataSet = this;\r
1728                                 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Constraints",\r
1729                                                                        typeof (ArrayList));\r
1730                                 if (dt.Constraints == null)\r
1731                                         dt.Constraints = new ConstraintCollection (dt);\r
1732                                 dt.DeserializeConstraints (arrayList);\r
1733                         }\r
1734                         arrayList = (ArrayList) info.GetValue ("DataSet.Relations",\r
1735                                                                typeof (ArrayList));\r
1736                         bool bParentColumn = true;\r
1737                         for (int l = 0; l < arrayList.Count; l++) {\r
1738                                 ArrayList tmpArrayList = (ArrayList) arrayList[l];\r
1739                                 ArrayList childColumns = new ArrayList ();\r
1740                                 ArrayList parentColumns = new ArrayList ();\r
1741                                 for (int k = 0; k < tmpArrayList.Count; k++) {\r
1742                                         if (tmpArrayList[k] != null && typeof (int) == tmpArrayList[k].GetType().GetElementType()) {\r
1743                                                 Array dataColumnArray = (Array)tmpArrayList[k];\r
1744                                                 if (bParentColumn) {\r
1745                                                         parentColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].\r
1746                                                                            Columns [(int) dataColumnArray.GetValue (1)]);\r
1747                                                         bParentColumn = false;\r
1748                                                 }\r
1749                                                 else {\r
1750                                                         childColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].\r
1751                                                                           Columns [(int) dataColumnArray.GetValue (1)]);\r
1752                                                         bParentColumn = true;\r
1753                                                 }\r
1754                                         }\r
1755                                 }\r
1756                                 Relations.Add ((string) tmpArrayList [0],\r
1757                                                (DataColumn []) parentColumns.ToArray (typeof (DataColumn)),\r
1758                                                (DataColumn []) childColumns.ToArray (typeof (DataColumn)),\r
1759                                                false);\r
1760                         }\r
1761                 }\r
1762 \r
1763                 private void OnDataSetInitialized (EventArgs e)\r
1764                 {\r
1765                         if (null != Initialized)\r
1766                                 Initialized (this, e);\r
1767                 }\r
1768 \r
1769                 private void DataSetInitialized ()\r
1770                 {\r
1771                         EventArgs e = new EventArgs ();\r
1772                         OnDataSetInitialized (e);\r
1773                 }\r
1774 \r
1775                 protected virtual void InitializeDerivedDataSet ()\r
1776                 {\r
1777                 }\r
1778 \r
1779                 protected SchemaSerializationMode DetermineSchemaSerializationMode (XmlReader reader)\r
1780                 {\r
1781                         return SchemaSerializationMode.IncludeSchema;\r
1782                 }\r
1783 \r
1784                 protected SchemaSerializationMode DetermineSchemaSerializationMode (SerializationInfo info, StreamingContext context)\r
1785                 {\r
1786                         SerializationInfoEnumerator e = info.GetEnumerator ();\r
1787                         while (e.MoveNext ()) {\r
1788                                 if (e.Name == "SchemaSerializationMode.DataSet") {\r
1789                                         return (SchemaSerializationMode) e.Value;\r
1790                                 }\r
1791                         }\r
1792                         \r
1793                         return SchemaSerializationMode.IncludeSchema;\r
1794                 }\r
1795 \r
1796                 protected bool IsBinarySerialized (SerializationInfo info, StreamingContext context)\r
1797                 {\r
1798                         SerializationInfoEnumerator e = info.GetEnumerator ();\r
1799                         while (e.MoveNext ()) {\r
1800                                 if (e.ObjectType == typeof (System.Data.SerializationFormat))\r
1801                                         return true;\r
1802                         }\r
1803                         return false;\r
1804                 }\r
1805         }\r
1806 #endif\r
1807 }\r