2009-10-29 Veerapuram Varadhan <vvaradhan@novell.com>
[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                         row.CopyValuesToRow (newRow);\r
572                         newRow.XmlRowID = row.XmlRowID;\r
573                         addedRows.Add (row, row);\r
574                 }\r
575 \r
576                 public string GetXml ()\r
577                 {\r
578                         StringWriter Writer = new StringWriter ();\r
579                         WriteXml (Writer, XmlWriteMode.IgnoreSchema);\r
580                         return Writer.ToString ();\r
581                 }\r
582 \r
583                 public string GetXmlSchema ()\r
584                 {\r
585                         StringWriter Writer = new StringWriter ();\r
586                         WriteXmlSchema (Writer);\r
587                         return Writer.ToString ();\r
588                 }\r
589 \r
590                 public bool HasChanges ()\r
591                 {\r
592                         return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
593                 }\r
594 \r
595                 public bool HasChanges (DataRowState rowStates)\r
596                 {\r
597                         if (((int) rowStates & 0xffffffe0) != 0)\r
598                                 throw new ArgumentOutOfRangeException ("rowStates");\r
599 \r
600                         DataTableCollection tableCollection = Tables;\r
601                         DataTable table;\r
602                         DataRowCollection rowCollection;\r
603                         DataRow row;\r
604 \r
605                         for (int i = 0; i < tableCollection.Count; i++) {\r
606                                 table = tableCollection [i];\r
607                                 rowCollection = table.Rows;\r
608                                 for (int j = 0; j < rowCollection.Count; j++) {\r
609                                         row = rowCollection [j];\r
610                                         if ((row.RowState & rowStates) != 0)\r
611                                                 return true;\r
612                                 }\r
613                         }\r
614 \r
615                         return false;\r
616                 }\r
617 \r
618                 public void InferXmlSchema (XmlReader reader, string[] nsArray)\r
619                 {\r
620                         if (reader == null)\r
621                                 return;\r
622                         XmlDocument doc = new XmlDocument ();\r
623                         doc.Load (reader);\r
624                         InferXmlSchema (doc, nsArray);\r
625                 }\r
626 \r
627                 private void InferXmlSchema (XmlDocument doc, string [] nsArray)\r
628                 {\r
629                         XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);\r
630                 }\r
631 \r
632                 public void InferXmlSchema (Stream stream, string[] nsArray)\r
633                 {\r
634                         InferXmlSchema (new XmlTextReader (stream), nsArray);\r
635                 }\r
636 \r
637                 public void InferXmlSchema (TextReader reader, string[] nsArray)\r
638                 {\r
639                         InferXmlSchema (new XmlTextReader (reader), nsArray);\r
640                 }\r
641 \r
642                 public void InferXmlSchema (string fileName, string[] nsArray)\r
643                 {\r
644                         XmlTextReader reader = new XmlTextReader (fileName);\r
645                         try {\r
646                                 InferXmlSchema (reader, nsArray);\r
647                         } finally {\r
648                                 reader.Close ();\r
649                         }\r
650                 }\r
651 \r
652                 public virtual void RejectChanges ()\r
653                 {\r
654                         int i;\r
655                         bool oldEnforceConstraints = this.EnforceConstraints;\r
656                         this.EnforceConstraints = false;\r
657 \r
658                         for (i = 0; i < this.Tables.Count;i++)\r
659                                 this.Tables[i].RejectChanges ();\r
660 \r
661                         this.EnforceConstraints = oldEnforceConstraints;\r
662                 }\r
663 \r
664                 public virtual void Reset ()\r
665                 {\r
666                         // first we remove all ForeignKeyConstraints (if we will not do that\r
667                         // we will get an exception when clearing the tables).\r
668                         for (int i = 0; i < Tables.Count; i++) {\r
669                                 ConstraintCollection cc = Tables[i].Constraints;\r
670                                 for (int j = 0; j < cc.Count; j++) {\r
671                                         if (cc[j] is ForeignKeyConstraint)\r
672                                                 cc.Remove (cc[j]);\r
673                                 }\r
674                         }\r
675 \r
676                         Clear ();\r
677                         Relations.Clear ();\r
678                         Tables.Clear ();\r
679                 }\r
680 \r
681                 public void WriteXml (Stream stream)\r
682                 {\r
683                         XmlTextWriter writer = new XmlTextWriter (stream, null);\r
684                         writer.Formatting = Formatting.Indented;\r
685                         WriteXml (writer);\r
686                 }\r
687 \r
688                 ///<summary>\r
689                 /// Writes the current data for the DataSet to the specified file.\r
690                 /// </summary>\r
691                 /// <param name="filename">Fully qualified filename to write to</param>\r
692                 public void WriteXml (string fileName)\r
693                 {\r
694                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
695                         writer.Formatting = Formatting.Indented;\r
696                         writer.WriteStartDocument (true);\r
697                         try {\r
698                                 WriteXml (writer);\r
699                         } finally {\r
700                                 writer.WriteEndDocument ();\r
701                                 writer.Close ();\r
702                         }\r
703                 }\r
704 \r
705                 public void WriteXml (TextWriter writer)\r
706                 {\r
707                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
708                         xwriter.Formatting = Formatting.Indented;\r
709                         WriteXml (xwriter);\r
710                 }\r
711 \r
712                 public void WriteXml (XmlWriter writer)\r
713                 {\r
714                         WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
715                 }\r
716 \r
717                 public void WriteXml (string fileName, XmlWriteMode mode)\r
718                 {\r
719                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
720                         writer.Formatting = Formatting.Indented;\r
721                         writer.WriteStartDocument (true);\r
722 \r
723                         try {\r
724                                 WriteXml (writer, mode);\r
725                         } finally {\r
726                                 writer.WriteEndDocument ();\r
727                                 writer.Close ();\r
728                         }\r
729                 }\r
730 \r
731                 public void WriteXml (Stream stream, XmlWriteMode mode)\r
732                 {\r
733                         XmlTextWriter writer = new XmlTextWriter (stream, null);\r
734                         writer.Formatting = Formatting.Indented;\r
735                         WriteXml (writer, mode);\r
736                 }\r
737 \r
738                 public void WriteXml (TextWriter writer, XmlWriteMode mode)\r
739                 {\r
740                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
741                         xwriter.Formatting = Formatting.Indented;\r
742                         WriteXml (xwriter, mode);\r
743                 }\r
744 \r
745                 public void WriteXml (XmlWriter writer, XmlWriteMode mode)\r
746                 {\r
747                         if (mode == XmlWriteMode.DiffGram) {\r
748                                 SetRowsID();\r
749                                 WriteDiffGramElement(writer);\r
750                         }\r
751 \r
752                         // It should not write when there is no content to be written\r
753                         bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);\r
754                         for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)\r
755                                 shouldOutputContent = tableCollection [n].Rows.Count > 0;\r
756 \r
757                         if (shouldOutputContent) {\r
758                                 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));\r
759 \r
760                                 if (mode == XmlWriteMode.WriteSchema)\r
761                                         DoWriteXmlSchema (writer);\r
762 \r
763                                 WriteTables (writer, mode, Tables, DataRowVersion.Default);\r
764                                 writer.WriteEndElement ();\r
765                         }\r
766 \r
767                         if (mode == XmlWriteMode.DiffGram) {\r
768                                 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {\r
769                                         DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);\r
770                                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
771                                         WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);\r
772                                         writer.WriteEndElement ();\r
773                                 }\r
774                         }\r
775 \r
776                         if (mode == XmlWriteMode.DiffGram)\r
777                                 writer.WriteEndElement (); // diffgr:diffgram\r
778 \r
779                         writer.Flush ();\r
780                 }\r
781 \r
782                 public void WriteXmlSchema (Stream stream)\r
783                 {\r
784                         XmlTextWriter writer = new XmlTextWriter (stream, null );\r
785                         writer.Formatting = Formatting.Indented;\r
786                         WriteXmlSchema (writer);\r
787                 }\r
788 \r
789                 public void WriteXmlSchema (string fileName)\r
790                 {\r
791                         XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
792                         try {\r
793                                 writer.Formatting = Formatting.Indented;\r
794                                 writer.WriteStartDocument (true);\r
795                                 WriteXmlSchema (writer);\r
796                         } finally {\r
797                                 writer.WriteEndDocument ();\r
798                                 writer.Close ();\r
799                         }\r
800                 }\r
801 \r
802                 public void WriteXmlSchema (TextWriter writer)\r
803                 {\r
804                         XmlTextWriter xwriter = new XmlTextWriter (writer);\r
805                         try {\r
806                                 xwriter.Formatting = Formatting.Indented;\r
807                                 WriteXmlSchema (xwriter);\r
808                         } finally {\r
809                                 xwriter.Close ();\r
810                         }\r
811                 }\r
812 \r
813                 public void WriteXmlSchema (XmlWriter writer)\r
814                 {\r
815                         //Create a skeleton doc and then write the schema\r
816                         //proper which is common to the WriteXml method in schema mode\r
817                         DoWriteXmlSchema (writer);\r
818                 }\r
819 \r
820                 public void ReadXmlSchema (Stream stream)\r
821                 {\r
822                         XmlReader reader = new XmlTextReader (stream, null);\r
823                         ReadXmlSchema (reader);\r
824                 }\r
825 \r
826                 public void ReadXmlSchema (string fileName)\r
827                 {\r
828                         XmlReader reader = new XmlTextReader (fileName);\r
829                         try {\r
830                                 ReadXmlSchema (reader);\r
831                         } finally {\r
832                                 reader.Close ();\r
833                         }\r
834                 }\r
835 \r
836                 public void ReadXmlSchema (TextReader reader)\r
837                 {\r
838                         XmlReader xr = new XmlTextReader (reader);\r
839                         ReadXmlSchema (xr);\r
840                 }\r
841 \r
842                 public void ReadXmlSchema (XmlReader reader)\r
843                 {\r
844 #if true\r
845                         XmlSchemaDataImporter xsdImporter = new XmlSchemaDataImporter (this, reader, true);\r
846                         xsdImporter.Process ();\r
847 #if NET_2_0\r
848                         tableAdapterSchemaInfo = xsdImporter.CurrentAdapter;\r
849 #endif\r
850 #else\r
851                         XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);\r
852                         SchemaMapper.Read (reader);\r
853 #endif\r
854                 }\r
855 \r
856                 public XmlReadMode ReadXml (Stream stream)\r
857                 {\r
858                         return ReadXml (new XmlTextReader (stream));\r
859                 }\r
860 \r
861                 public XmlReadMode ReadXml (string fileName)\r
862                 {\r
863                         XmlTextReader reader = new XmlTextReader (fileName);\r
864                         try {\r
865                                 return ReadXml (reader);\r
866                         } finally {\r
867                                 reader.Close ();\r
868                         }\r
869                 }\r
870 \r
871                 public XmlReadMode ReadXml (TextReader reader)\r
872                 {\r
873                         return ReadXml (new XmlTextReader (reader));\r
874                 }\r
875 \r
876                 public XmlReadMode ReadXml (XmlReader reader)\r
877                 {\r
878                         return ReadXml (reader, XmlReadMode.Auto);\r
879                 }\r
880 \r
881                 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)\r
882                 {\r
883                         return ReadXml (new XmlTextReader (stream), mode);\r
884                 }\r
885 \r
886                 public XmlReadMode ReadXml (string fileName, XmlReadMode mode)\r
887                 {\r
888                         XmlTextReader reader = new XmlTextReader (fileName);\r
889                         try {\r
890                                 return ReadXml (reader, mode);\r
891                         } finally {\r
892                                 reader.Close ();\r
893                         }\r
894                 }\r
895 \r
896                 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)\r
897                 {\r
898                         return ReadXml (new XmlTextReader (reader), mode);\r
899                 }\r
900 \r
901                 // LAMESPEC: XmlReadMode.Fragment is far from presisely\r
902                 // documented. MS.NET infers schema against this mode.\r
903                 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)\r
904                 {\r
905                         if (reader == null)\r
906                                 return mode;\r
907 \r
908                         switch (reader.ReadState) {\r
909                         case ReadState.EndOfFile:\r
910                         case ReadState.Error:\r
911                         case ReadState.Closed:\r
912                                 return mode;\r
913                         }\r
914                         // Skip XML declaration and prolog\r
915                         reader.MoveToContent ();\r
916                         if (reader.EOF)\r
917                                 return mode;\r
918 \r
919                         if (reader is XmlTextReader) {\r
920                                 // we dont need whitespace\r
921                                 ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.None;\r
922                         }\r
923 \r
924                         XmlDiffLoader DiffLoader = null;\r
925 \r
926                         // If diffgram, then read the first element as diffgram\r
927                         if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {\r
928                                 switch (mode) {\r
929                                         case XmlReadMode.Auto:\r
930                                         case XmlReadMode.DiffGram:\r
931                                                 if (DiffLoader == null)\r
932                                                         DiffLoader = new XmlDiffLoader (this);\r
933                                                 DiffLoader.Load (reader);\r
934                                                 // (and leave rest of the reader as is)\r
935                                                 return XmlReadMode.DiffGram;\r
936                                         case XmlReadMode.Fragment:\r
937                                                 reader.Skip ();\r
938                                                 // (and continue to read)\r
939                                                 break;\r
940                                         default:\r
941                                                 reader.Skip ();\r
942                                                 // (and leave rest of the reader as is)\r
943                                                 return mode;\r
944                                 }\r
945                         }\r
946 \r
947                         // If schema, then read the first element as schema\r
948                         if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
949                                 switch (mode) {\r
950                                         case XmlReadMode.IgnoreSchema:\r
951                                         case XmlReadMode.InferSchema:\r
952                                                 reader.Skip ();\r
953                                                 // (and break up read)\r
954                                                 return mode;\r
955                                         case XmlReadMode.Fragment:\r
956                                                 ReadXmlSchema (reader);\r
957                                                 // (and continue to read)\r
958                                                 break;\r
959                                         case XmlReadMode.Auto:\r
960                                                 if (Tables.Count == 0) {\r
961                                                         ReadXmlSchema (reader);\r
962                                                         return XmlReadMode.ReadSchema;\r
963                                                 } else {\r
964                                                         // otherwise just ignore and return IgnoreSchema\r
965                                                         reader.Skip ();\r
966                                                         return XmlReadMode.IgnoreSchema;\r
967                                                 }\r
968                                         default:\r
969                                                 ReadXmlSchema (reader);\r
970                                                 // (and leave rest of the reader as is)\r
971                                                 return mode; // When DiffGram, return DiffGram\r
972                                 }\r
973                         }\r
974 \r
975                         if (reader.EOF)\r
976                                 return mode;\r
977 \r
978                         int depth = (reader.NodeType == XmlNodeType.Element) ? reader.Depth : -1;\r
979 \r
980                         XmlDocument doc = new XmlDocument ();\r
981                         XmlElement root = doc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);\r
982                         if (reader.HasAttributes) {\r
983                                 for (int i = 0; i < reader.AttributeCount; i++) {\r
984                                         reader.MoveToAttribute(i);\r
985                                         if (reader.NamespaceURI == XmlConstants.XmlnsNS)\r
986                                                 root.SetAttribute(reader.Name, reader.GetAttribute(i));\r
987                                         else {\r
988                                                 XmlAttribute attr = root.SetAttributeNode(reader.LocalName, reader.NamespaceURI);\r
989                                                 attr.Prefix = reader.Prefix;\r
990                                                 attr.Value = reader.GetAttribute(i);\r
991                                         }\r
992                                 }\r
993                         }\r
994 \r
995                         reader.Read();\r
996                         XmlReadMode retMode = mode;\r
997                         bool schemaLoaded = false;\r
998 \r
999                         for (;;) {\r
1000                                 if( reader.Depth == depth ||\r
1001                                         reader.NodeType == XmlNodeType.EndElement)\r
1002                                         break;\r
1003 \r
1004                                 if (reader.NodeType != XmlNodeType.Element) {\r
1005                                         if (!reader.Read())\r
1006                                                 break;\r
1007                                         continue;\r
1008                                 }\r
1009 \r
1010                                 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
1011                                         switch (mode) {\r
1012                                                 case XmlReadMode.IgnoreSchema:\r
1013                                                 case XmlReadMode.InferSchema:\r
1014                                                         reader.Skip ();\r
1015                                                         break;\r
1016 \r
1017                                                 default:\r
1018                                                         ReadXmlSchema (reader);\r
1019                                                         retMode = XmlReadMode.ReadSchema;\r
1020                                                         schemaLoaded = true;\r
1021                                                         // (and leave rest of the reader as is)\r
1022                                                         break;\r
1023                                         }\r
1024 \r
1025                                         continue;\r
1026                                 }\r
1027 \r
1028                                 if ((reader.LocalName == "diffgram") && (reader.NamespaceURI == XmlConstants.DiffgrNamespace)) {\r
1029                                         if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)\r
1030                                                 || mode == XmlReadMode.Auto) {\r
1031                                                 if (DiffLoader == null)\r
1032                                                         DiffLoader = new XmlDiffLoader (this);\r
1033                                                 DiffLoader.Load (reader);\r
1034                                                 // (and leave rest of the reader as is)\r
1035                                                 retMode = XmlReadMode.DiffGram;\r
1036                                         }\r
1037                                         else\r
1038                                                 reader.Skip();\r
1039 \r
1040                                         continue;\r
1041                                 }\r
1042 \r
1043                                 //collect data\r
1044                                 XmlNode n = doc.ReadNode(reader);\r
1045                                 root.AppendChild(n);\r
1046                         }\r
1047 \r
1048                         if (reader.NodeType == XmlNodeType.EndElement)\r
1049                                 reader.Read ();\r
1050                         reader.MoveToContent();\r
1051 \r
1052                         if (mode == XmlReadMode.DiffGram) {\r
1053                                 return retMode;\r
1054                         }\r
1055 \r
1056                         doc.AppendChild(root);\r
1057 \r
1058                         if (!schemaLoaded &&\r
1059                                 retMode != XmlReadMode.ReadSchema &&\r
1060                                 mode != XmlReadMode.IgnoreSchema &&\r
1061                                 mode != XmlReadMode.Fragment &&\r
1062                                 (Tables.Count == 0 || mode == XmlReadMode.InferSchema)) {\r
1063                                 InferXmlSchema(doc, null);\r
1064                                 if (mode == XmlReadMode.Auto)\r
1065                                         retMode = XmlReadMode.InferSchema;\r
1066                         }\r
1067 \r
1068                         reader = new XmlNodeReader (doc);\r
1069                         XmlDataReader.ReadXml (this, reader, mode);\r
1070 \r
1071                         return retMode == XmlReadMode.Auto ?\r
1072                                 XmlReadMode.IgnoreSchema : retMode;\r
1073                 }\r
1074                 #endregion // Public Methods\r
1075 \r
1076                 #region Public Events\r
1077 \r
1078                 [DataCategory ("Action")]\r
1079 #if !NET_2_0\r
1080                 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]\r
1081 #endif\r
1082                 public event MergeFailedEventHandler MergeFailed;\r
1083 \r
1084                 #endregion // Public Events\r
1085 \r
1086                 #region IListSource methods\r
1087                 IList IListSource.GetList ()\r
1088                 {\r
1089                         return DefaultViewManager;\r
1090                 }\r
1091 \r
1092                 bool IListSource.ContainsListCollection {\r
1093                         get {\r
1094                                 return true;\r
1095                         }\r
1096                 }\r
1097                 #endregion IListSource methods\r
1098 \r
1099                 #region ISupportInitialize methods\r
1100 \r
1101                 internal bool InitInProgress {\r
1102                         get { return initInProgress; }\r
1103                         set { initInProgress = value; }\r
1104                 }\r
1105 \r
1106                 public void BeginInit ()\r
1107                 {\r
1108                         InitInProgress = true;\r
1109 #if NET_2_0\r
1110                         dataSetInitialized = false;\r
1111 #endif\r
1112                 }\r
1113 \r
1114                 public void EndInit ()\r
1115                 {\r
1116                         // Finsh the init'ing the tables only after adding all the\r
1117                         // tables to the collection.\r
1118                         Tables.PostAddRange ();\r
1119                         for (int i=0; i < Tables.Count; ++i) {\r
1120                                 if (!Tables [i].InitInProgress)\r
1121                                         continue;\r
1122                                 Tables [i].FinishInit ();\r
1123                         }\r
1124 \r
1125                         Relations.PostAddRange ();\r
1126                         InitInProgress = false;\r
1127 #if NET_2_0\r
1128                         dataSetInitialized = true;\r
1129                         DataSetInitialized ();\r
1130 #endif\r
1131                 }\r
1132                 #endregion\r
1133 \r
1134                 #region ISerializable\r
1135 #if NET_2_0\r
1136                 public virtual\r
1137 #endif\r
1138                 void\r
1139 #if !NET_2_0\r
1140                 ISerializable.\r
1141 #endif\r
1142                 GetObjectData (SerializationInfo info, StreamingContext context)\r
1143                 {\r
1144 #if NET_2_0\r
1145                         if (RemotingFormat == SerializationFormat.Xml) {\r
1146                                 info.AddValue ("SchemaSerializationMode.DataSet", this.SchemaSerializationMode);\r
1147 #endif\r
1148                                 StringWriter sw = new StringWriter ();\r
1149                                 XmlTextWriter writer = new XmlTextWriter (sw);\r
1150                                 DoWriteXmlSchema (writer);\r
1151                                 writer.Flush ();\r
1152                                 info.AddValue ("XmlSchema", sw.ToString ());\r
1153 \r
1154                                 sw = new StringWriter ();\r
1155                                 writer = new XmlTextWriter (sw);\r
1156                                 WriteXml (writer, XmlWriteMode.DiffGram);\r
1157                                 writer.Flush ();\r
1158                                 info.AddValue ("XmlDiffGram", sw.ToString ());\r
1159 #if NET_2_0\r
1160                         } else /*if (DataSet.RemotingFormat == SerializationFormat.Binary)*/ {\r
1161                                 BinarySerialize (info);\r
1162                         }\r
1163 #endif\r
1164                 }\r
1165                 #endregion\r
1166 \r
1167                 #region Protected Methods\r
1168                 protected void GetSerializationData (SerializationInfo info, StreamingContext context)\r
1169                 {\r
1170                         string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;\r
1171                         XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
1172                         ReadXml (reader, XmlReadMode.DiffGram);\r
1173                         reader.Close ();\r
1174                 }\r
1175 \r
1176 \r
1177                 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()\r
1178                 {\r
1179                         return null;\r
1180                 }\r
1181 \r
1182                 protected virtual void ReadXmlSerializable (XmlReader reader)\r
1183                 {\r
1184                         ReadXml (reader, XmlReadMode.DiffGram);\r
1185                 }\r
1186 \r
1187                 void IXmlSerializable.ReadXml (XmlReader reader)\r
1188                 {\r
1189                         ReadXmlSerializable(reader);\r
1190                 }\r
1191 \r
1192                 void IXmlSerializable.WriteXml (XmlWriter writer)\r
1193                 {\r
1194                         DoWriteXmlSchema (writer);\r
1195                         WriteXml (writer, XmlWriteMode.DiffGram);\r
1196                 }\r
1197 \r
1198                 XmlSchema IXmlSerializable.GetSchema ()\r
1199                 {\r
1200                         if (GetType() == typeof(DataSet))\r
1201                                 return null;\r
1202                         MemoryStream stream = new MemoryStream();\r
1203                         XmlTextWriter writer = new XmlTextWriter(stream, null);\r
1204                         WriteXmlSchema(writer);\r
1205                         stream.Position = 0;\r
1206                         return XmlSchema.Read(new XmlTextReader(stream), (ValidationEventHandler)null);\r
1207                 }\r
1208 \r
1209                 protected virtual bool ShouldSerializeRelations ()\r
1210                 {\r
1211                         return true;\r
1212                 }\r
1213 \r
1214                 protected virtual bool ShouldSerializeTables ()\r
1215                 {\r
1216                         return true;\r
1217                 }\r
1218 \r
1219                 [MonoTODO]\r
1220                 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)\r
1221                 {\r
1222                         throw new NotImplementedException ();\r
1223                 }\r
1224 \r
1225                 [MonoTODO]\r
1226                 protected virtual void OnRemoveRelation (DataRelation relation)\r
1227                 {\r
1228                         throw new NotImplementedException ();\r
1229                 }\r
1230 \r
1231                 [MonoTODO]\r
1232                 protected virtual void OnRemoveTable (DataTable table)\r
1233                 {\r
1234                         throw new NotImplementedException ();\r
1235                 }\r
1236 \r
1237                 internal virtual void OnMergeFailed (MergeFailedEventArgs e)\r
1238                 {\r
1239                         if (MergeFailed != null)\r
1240                                 MergeFailed (this, e);\r
1241                         else\r
1242                                 throw new DataException (e.Conflict);\r
1243                 }\r
1244 \r
1245                 [MonoTODO]\r
1246                 protected internal void RaisePropertyChanging (string name)\r
1247                 {\r
1248                 }\r
1249 \r
1250                 #endregion\r
1251 \r
1252                 #region Private Methods\r
1253 \r
1254                 internal static string WriteObjectXml (object o)\r
1255                 {\r
1256                         switch (Type.GetTypeCode (o.GetType ())) {\r
1257                                 case TypeCode.Boolean:\r
1258                                         return XmlConvert.ToString ((Boolean) o);\r
1259                                 case TypeCode.Byte:\r
1260                                         return XmlConvert.ToString ((Byte) o);\r
1261                                 case TypeCode.Char:\r
1262                                         return XmlConvert.ToString ((Char) o);\r
1263                                 case TypeCode.DateTime:\r
1264 #if NET_2_0\r
1265                                         return XmlConvert.ToString ((DateTime) o, XmlDateTimeSerializationMode.Unspecified);\r
1266 #else\r
1267                                         return XmlConvert.ToString ((DateTime) o);\r
1268 #endif\r
1269                                 case TypeCode.Decimal:\r
1270                                         return XmlConvert.ToString ((Decimal) o);\r
1271                                 case TypeCode.Double:\r
1272                                         return XmlConvert.ToString ((Double) o);\r
1273                                 case TypeCode.Int16:\r
1274                                         return XmlConvert.ToString ((Int16) o);\r
1275                                 case TypeCode.Int32:\r
1276                                         return XmlConvert.ToString ((Int32) o);\r
1277                                 case TypeCode.Int64:\r
1278                                         return XmlConvert.ToString ((Int64) o);\r
1279                                 case TypeCode.SByte:\r
1280                                         return XmlConvert.ToString ((SByte) o);\r
1281                                 case TypeCode.Single:\r
1282                                         return XmlConvert.ToString ((Single) o);\r
1283                                 case TypeCode.UInt16:\r
1284                                         return XmlConvert.ToString ((UInt16) o);\r
1285                                 case TypeCode.UInt32:\r
1286                                         return XmlConvert.ToString ((UInt32) o);\r
1287                                 case TypeCode.UInt64:\r
1288                                         return XmlConvert.ToString ((UInt64) o);\r
1289                         }\r
1290                         if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);\r
1291                         if (o is Guid) return XmlConvert.ToString ((Guid) o);\r
1292                         if (o is byte[]) return Convert.ToBase64String ((byte[])o);\r
1293 \r
1294                         return o.ToString ();\r
1295                 }\r
1296 \r
1297                 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)\r
1298                 {\r
1299                         //WriteTable takes care of skipping a table if it has a\r
1300                         //Nested Parent Relationship\r
1301                         foreach (DataTable table in tableCollection)\r
1302                                 WriteTable ( writer, table, mode, version);\r
1303                 }\r
1304 \r
1305                 internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)\r
1306                 {\r
1307                         DataRow[] rows = table.NewRowArray(table.Rows.Count);\r
1308                         table.Rows.CopyTo (rows, 0);\r
1309                         WriteTable (writer, rows, mode, version, true);\r
1310                 }\r
1311 \r
1312                 internal static void WriteTable (XmlWriter writer,\r
1313                         DataRow [] rows,\r
1314                         XmlWriteMode mode,\r
1315                         DataRowVersion version, bool skipIfNested)\r
1316                 {\r
1317                         if (rows.Length == 0) return;\r
1318                         DataTable table = rows[0].Table;\r
1319 \r
1320                         if (table.TableName == null || table.TableName == "")\r
1321                                 throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");\r
1322 \r
1323                         //The columns can be attributes, hidden, elements, or simple content\r
1324                         //There can be 0-1 simple content cols or 0-* elements\r
1325                         System.Collections.ArrayList atts;\r
1326                         System.Collections.ArrayList elements;\r
1327                         DataColumn simple = null;\r
1328 \r
1329                         SplitColumns (table, out atts, out elements, out simple);\r
1330                         //sort out the namespacing\r
1331                         int relationCount = table.ParentRelations.Count;\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                                 ((IXmlSerializable)rowObject).WriteXml (writer);\r
1407                         } else {\r
1408                                 writer.WriteString (WriteObjectXml (rowObject));\r
1409                         }\r
1410 \r
1411                         writer.WriteEndElement ();\r
1412                 }\r
1413 \r
1414                 internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)\r
1415                 {\r
1416                         if (!row.IsNull (col))\r
1417                                 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));\r
1418                 }\r
1419 \r
1420                 internal static void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)\r
1421                 {\r
1422                         //sort out the namespacing\r
1423                         string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;\r
1424 \r
1425                         WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));\r
1426 \r
1427                         if (mode == XmlWriteMode.DiffGram) {\r
1428                                 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));\r
1429                                 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));\r
1430                                 string modeName = null;\r
1431                                 if (row.RowState == DataRowState.Modified)\r
1432                                         modeName = "modified";\r
1433                                 else if (row.RowState == DataRowState.Added)\r
1434                                         modeName = "inserted";\r
1435 \r
1436                                 if (version != DataRowVersion.Original && modeName != null)\r
1437                                         WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);\r
1438                         }\r
1439                 }\r
1440 \r
1441                 internal static void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)\r
1442                 {\r
1443                         writer.WriteStartElement (prefix, name, nspc);\r
1444                 }\r
1445 \r
1446                 internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)\r
1447                 {\r
1448                         switch ( mode) {\r
1449                         //      case XmlWriteMode.WriteSchema:\r
1450                         //              writer.WriteAttributeString (prefix, name, nspc);\r
1451                         //              break;\r
1452                                 case XmlWriteMode.DiffGram:\r
1453                                         writer.WriteAttributeString (prefix, name, nspc,stringValue);\r
1454                                         break;\r
1455                                 default:\r
1456                                         writer.WriteAttributeString (name, stringValue);\r
1457                                         break;\r
1458                         };\r
1459                 }\r
1460 \r
1461                 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)\r
1462                 {\r
1463                         if (mode == XmlWriteMode.DiffGram) {\r
1464                                 table.SetRowsID ();\r
1465                                 WriteDiffGramElement (writer);\r
1466                         }\r
1467 \r
1468                         WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));\r
1469 \r
1470                         WriteTable (writer, table, mode, DataRowVersion.Default);\r
1471 \r
1472                         if (mode == XmlWriteMode.DiffGram) {\r
1473                                 writer.WriteEndElement (); //DataSet name\r
1474                                 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {\r
1475 \r
1476                                         DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);\r
1477                                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
1478                                         WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);\r
1479                                         writer.WriteEndElement ();\r
1480                                 }\r
1481                         }\r
1482                         writer.WriteEndElement (); // DataSet name or diffgr:diffgram\r
1483                 }\r
1484 \r
1485                 private void DoWriteXmlSchema (XmlWriter writer)\r
1486                 {\r
1487                         if (writer.WriteState == WriteState.Start)\r
1488                                 writer.WriteStartDocument ();\r
1489                         XmlSchemaWriter.WriteXmlSchema (this, writer);\r
1490                 }\r
1491 \r
1492                 ///<summary>\r
1493                 /// Helper function to split columns into attributes elements and simple\r
1494                 /// content\r
1495                 /// </summary>\r
1496                 internal static void SplitColumns (DataTable table,\r
1497                         out ArrayList atts,\r
1498                         out ArrayList elements,\r
1499                         out DataColumn simple)\r
1500                 {\r
1501                         //The columns can be attributes, hidden, elements, or simple content\r
1502                         //There can be 0-1 simple content cols or 0-* elements\r
1503                         atts = new System.Collections.ArrayList ();\r
1504                         elements = new System.Collections.ArrayList ();\r
1505                         simple = null;\r
1506 \r
1507                         //Sort out the columns\r
1508                         foreach (DataColumn col in table.Columns) {\r
1509                                 switch (col.ColumnMapping) {\r
1510                                         case MappingType.Attribute:\r
1511                                                 atts.Add (col);\r
1512                                                 break;\r
1513                                         case MappingType.Element:\r
1514                                                 elements.Add (col);\r
1515                                                 break;\r
1516                                         case MappingType.SimpleContent:\r
1517                                                 if (simple != null) {\r
1518                                                         throw new System.InvalidOperationException ("There may only be one simple content element");\r
1519                                                 }\r
1520                                                 simple = col;\r
1521                                                 break;\r
1522                                         default:\r
1523                                                 //ignore Hidden elements\r
1524                                                 break;\r
1525                                 }\r
1526                         }\r
1527                 }\r
1528 \r
1529                 internal static void WriteDiffGramElement (XmlWriter writer)\r
1530                 {\r
1531                         WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");\r
1532                         WriteAttributeString (writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);\r
1533                 }\r
1534 \r
1535                 private void SetRowsID ()\r
1536                 {\r
1537                         foreach (DataTable table in Tables)\r
1538                                 table.SetRowsID ();\r
1539                 }\r
1540 \r
1541                 #endregion //Private Xml Serialisation\r
1542         }\r
1543 \r
1544 #if NET_2_0\r
1545         [XmlSchemaProvider ("GetDataSetSchema")]\r
1546         [XmlRoot ("DataSet")]\r
1547         partial class DataSet : ISupportInitializeNotification {\r
1548                 private bool dataSetInitialized = true;\r
1549                 public event EventHandler Initialized;\r
1550 \r
1551                 protected DataSet (SerializationInfo info, StreamingContext context, bool constructSchema)\r
1552                         : this ()\r
1553                 {\r
1554                         if (DetermineSchemaSerializationMode (info, context) == SchemaSerializationMode.ExcludeSchema) {\r
1555                                 InitializeDerivedDataSet ();\r
1556                         }\r
1557                         \r
1558                         if (IsBinarySerialized (info, context)) {\r
1559                                 BinaryDeserialize (info);\r
1560                                 return;\r
1561                         }\r
1562                         \r
1563                         if (constructSchema) {\r
1564                                 string s = info.GetValue ("XmlSchema", typeof (String)) as String;\r
1565                                 XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
1566                                 ReadXmlSchema (reader);\r
1567                                 reader.Close ();\r
1568                                 \r
1569                                 GetSerializationData (info, context);\r
1570                         }\r
1571                 }\r
1572 \r
1573                 SerializationFormat remotingFormat = SerializationFormat.Xml;\r
1574                 [DefaultValue (SerializationFormat.Xml)]\r
1575                 public SerializationFormat RemotingFormat {\r
1576                         get { return remotingFormat; }\r
1577                         set { remotingFormat = value; }\r
1578                 }\r
1579 \r
1580                 [Browsable (false)]\r
1581                 public bool IsInitialized {\r
1582                         get { return dataSetInitialized; }\r
1583                 }\r
1584 \r
1585                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
1586                 [Browsable (false)]\r
1587                 public virtual SchemaSerializationMode SchemaSerializationMode {\r
1588                         get { return SchemaSerializationMode.IncludeSchema; }\r
1589                         set {\r
1590                                 if (value != SchemaSerializationMode.IncludeSchema)\r
1591                                         throw new InvalidOperationException (\r
1592                                                         "Only IncludeSchema Mode can be set for Untyped DataSet");\r
1593                         }\r
1594                 }\r
1595 \r
1596                 public DataTableReader CreateDataReader (params DataTable[] dataTables)\r
1597                 {\r
1598                         return new DataTableReader (dataTables);\r
1599                 }\r
1600 \r
1601                 public DataTableReader CreateDataReader ()\r
1602                 {\r
1603                         return new DataTableReader ((DataTable[])Tables.ToArray (typeof (DataTable)));\r
1604                 }\r
1605 \r
1606                 public static XmlSchemaComplexType GetDataSetSchema (XmlSchemaSet schemaSet)\r
1607                 {\r
1608                         return new XmlSchemaComplexType ();\r
1609                 }\r
1610 \r
1611                 public void Load (IDataReader reader, LoadOption loadOption, params DataTable[] tables)\r
1612                 {\r
1613                         if (reader == null)\r
1614                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1615 \r
1616                         foreach (DataTable dt in tables) {\r
1617                                 if (dt.DataSet == null || dt.DataSet != this)\r
1618                                         throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");\r
1619                                 dt.Load (reader, loadOption);\r
1620                                 reader.NextResult ();\r
1621                         }\r
1622                 }\r
1623 \r
1624                 public void Load (IDataReader reader, LoadOption loadOption, params string[] tables)\r
1625                 {\r
1626                         if (reader == null)\r
1627                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1628 \r
1629                         foreach (string tableName in tables) {\r
1630                                 DataTable dt = Tables [tableName];\r
1631 \r
1632                                 if (dt == null) {\r
1633                                         dt = new DataTable (tableName);\r
1634                                         Tables.Add (dt);\r
1635                                 }\r
1636                                 dt.Load (reader, loadOption);\r
1637                                 reader.NextResult ();\r
1638                         }\r
1639                 }\r
1640 \r
1641                 public virtual void Load (IDataReader reader, LoadOption loadOption,\r
1642                                           FillErrorEventHandler errorHandler, params DataTable[] tables)\r
1643                 {\r
1644                         if (reader == null)\r
1645                                 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");\r
1646 \r
1647                         foreach (DataTable dt in tables) {\r
1648                                 if (dt.DataSet == null || dt.DataSet != this)\r
1649                                         throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");\r
1650                                 dt.Load (reader, loadOption, errorHandler);\r
1651                                 reader.NextResult ();\r
1652                         }\r
1653                 }\r
1654 \r
1655                 void BinarySerialize (SerializationInfo si)\r
1656                 {\r
1657                         Version vr = new Version(2, 0);\r
1658                         si.AddValue ("DataSet.RemotingVersion", vr, typeof (Version));\r
1659                         si.AddValue ("DataSet.RemotingFormat", RemotingFormat, typeof (SerializationFormat));\r
1660                         si.AddValue ("DataSet.DataSetName", DataSetName);\r
1661                         si.AddValue ("DataSet.Namespace", Namespace);\r
1662                         si.AddValue ("DataSet.Prefix", Prefix);\r
1663                         si.AddValue ("DataSet.CaseSensitive", CaseSensitive);\r
1664                         si.AddValue ("DataSet.LocaleLCID", Locale.LCID);\r
1665                         si.AddValue ("DataSet.EnforceConstraints", EnforceConstraints);\r
1666                         si.AddValue ("DataSet.ExtendedProperties", properties, typeof (PropertyCollection));\r
1667 \r
1668                         Tables.BinarySerialize_Schema (si);\r
1669                         Tables.BinarySerialize_Data (si);\r
1670 \r
1671                         Relations.BinarySerialize (si);\r
1672                 }\r
1673 \r
1674                 void BinaryDeserialize (SerializationInfo info)\r
1675                 {\r
1676                         ArrayList arrayList = null;\r
1677 \r
1678                         DataSetName = info.GetString ("DataSet.DataSetName");\r
1679                         Namespace = info.GetString ("DataSet.Namespace");\r
1680                         CaseSensitive = info.GetBoolean ("DataSet.CaseSensitive");\r
1681                         Locale = new CultureInfo (info.GetInt32 ("DataSet.LocaleLCID"));\r
1682                         EnforceConstraints = info.GetBoolean ("DataSet.EnforceConstraints");\r
1683                         Prefix = info.GetString ("DataSet.Prefix");\r
1684                         /*\r
1685                           FIXME: Private variable available in SerializationInfo\r
1686                           this.RemotingVersion = (System.Version) info.GetValue("DataSet.RemotingVersion",\r
1687                           typeof(System.Version));\r
1688                         */\r
1689                         properties = (PropertyCollection) info.GetValue ("DataSet.ExtendedProperties",\r
1690                                                                          typeof (PropertyCollection));\r
1691                         int tableCount = info.GetInt32 ("DataSet.Tables.Count");\r
1692 \r
1693                         Byte [] bytes;\r
1694                         DataTable dt = null;\r
1695                         for (int i = 0; i < tableCount; i++) {\r
1696                                 bytes = (Byte []) info.GetValue ("DataSet.Tables_" + i,\r
1697                                                                  typeof (Byte[]));\r
1698                                 MemoryStream ms = new MemoryStream (bytes);\r
1699                                 BinaryFormatter bf = new BinaryFormatter ();\r
1700                                 dt = (DataTable) bf.Deserialize (ms);\r
1701                                 ms.Close ();\r
1702                                 for (int j = 0; j < dt.Columns.Count; j++) {\r
1703                                         dt.Columns[j].Expression = info.GetString ("DataTable_" + i +\r
1704                                                                                    ".DataColumn_" + j +\r
1705                                                                                    ".Expression");\r
1706                                 }\r
1707                                 /*\r
1708                                   Not using\r
1709                                   int rowsCount = info.GetInt32 ("DataTable_" + i + ".Rows.Count");\r
1710                                   int recordsCount = info.GetInt32 ("DataTable_" + i + ".Records.Count");\r
1711                                 */\r
1712                                 ArrayList nullBits = (ArrayList) info.GetValue ("DataTable_" + i + ".NullBits",\r
1713                                                                                 typeof (ArrayList));\r
1714                                 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Records",\r
1715                                                                        typeof (ArrayList));\r
1716                                 BitArray rowStateBitArray = (BitArray) info.GetValue ("DataTable_" + i + ".RowStates",\r
1717                                                                                       typeof (BitArray));\r
1718                                 dt.DeserializeRecords (arrayList, nullBits, rowStateBitArray);\r
1719                                 Tables.Add (dt);\r
1720                         }\r
1721                         for (int i = 0; i < tableCount; i++) {\r
1722                                 dt = Tables [i];\r
1723                                 dt.dataSet = this;\r
1724                                 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Constraints",\r
1725                                                                        typeof (ArrayList));\r
1726                                 if (dt.Constraints == null)\r
1727                                         dt.Constraints = new ConstraintCollection (dt);\r
1728                                 dt.DeserializeConstraints (arrayList);\r
1729                         }\r
1730                         arrayList = (ArrayList) info.GetValue ("DataSet.Relations",\r
1731                                                                typeof (ArrayList));\r
1732                         bool bParentColumn = true;\r
1733                         for (int l = 0; l < arrayList.Count; l++) {\r
1734                                 ArrayList tmpArrayList = (ArrayList) arrayList[l];\r
1735                                 ArrayList childColumns = new ArrayList ();\r
1736                                 ArrayList parentColumns = new ArrayList ();\r
1737                                 for (int k = 0; k < tmpArrayList.Count; k++) {\r
1738                                         if (tmpArrayList[k] != null && typeof (int) == tmpArrayList[k].GetType().GetElementType()) {\r
1739                                                 Array dataColumnArray = (Array)tmpArrayList[k];\r
1740                                                 if (bParentColumn) {\r
1741                                                         parentColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].\r
1742                                                                            Columns [(int) dataColumnArray.GetValue (1)]);\r
1743                                                         bParentColumn = false;\r
1744                                                 }\r
1745                                                 else {\r
1746                                                         childColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].\r
1747                                                                           Columns [(int) dataColumnArray.GetValue (1)]);\r
1748                                                         bParentColumn = true;\r
1749                                                 }\r
1750                                         }\r
1751                                 }\r
1752                                 Relations.Add ((string) tmpArrayList [0],\r
1753                                                (DataColumn []) parentColumns.ToArray (typeof (DataColumn)),\r
1754                                                (DataColumn []) childColumns.ToArray (typeof (DataColumn)),\r
1755                                                false);\r
1756                         }\r
1757                 }\r
1758 \r
1759                 private void OnDataSetInitialized (EventArgs e)\r
1760                 {\r
1761                         if (null != Initialized)\r
1762                                 Initialized (this, e);\r
1763                 }\r
1764 \r
1765                 private void DataSetInitialized ()\r
1766                 {\r
1767                         EventArgs e = new EventArgs ();\r
1768                         OnDataSetInitialized (e);\r
1769                 }\r
1770 \r
1771                 protected virtual void InitializeDerivedDataSet ()\r
1772                 {\r
1773                 }\r
1774 \r
1775                 protected SchemaSerializationMode DetermineSchemaSerializationMode (XmlReader reader)\r
1776                 {\r
1777                         return SchemaSerializationMode.IncludeSchema;\r
1778                 }\r
1779 \r
1780                 protected SchemaSerializationMode DetermineSchemaSerializationMode (SerializationInfo info, StreamingContext context)\r
1781                 {\r
1782                         SerializationInfoEnumerator e = info.GetEnumerator ();\r
1783                         while (e.MoveNext ()) {\r
1784                                 if (e.Name == "SchemaSerializationMode.DataSet") {\r
1785                                         return (SchemaSerializationMode) e.Value;\r
1786                                 }\r
1787                         }\r
1788                         \r
1789                         return SchemaSerializationMode.IncludeSchema;\r
1790                 }\r
1791 \r
1792                 protected bool IsBinarySerialized (SerializationInfo info, StreamingContext context)\r
1793                 {\r
1794                         SerializationInfoEnumerator e = info.GetEnumerator ();\r
1795                         while (e.MoveNext ()) {\r
1796                                 if (e.ObjectType == typeof (System.Data.SerializationFormat))\r
1797                                         return true;\r
1798                         }\r
1799                         return false;\r
1800                 }\r
1801         }\r
1802 #endif\r
1803 }\r