2 // System.Data/DataSet.cs
\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
14 // (C) Ximian, Inc. 2002
\r
15 // Copyright (C) Tim Coleman, 2002, 2003
\r
19 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
\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
29 // The above copyright notice and this permission notice shall be
\r
30 // included in all copies or substantial portions of the Software.
\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
42 using System.Collections;
\r
43 using System.ComponentModel;
\r
44 using System.Globalization;
\r
45 using System.Threading;
\r
47 using System.Runtime.Serialization;
\r
48 using System.Runtime.Serialization.Formatters.Binary;
\r
50 using System.Xml.Schema;
\r
51 using System.Xml.Serialization;
\r
52 using System.Data.Common;
\r
54 namespace System.Data
\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
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 bool initInProgress;
\r
75 #region Constructors
\r
78 : this ("NewDataSet")
\r
82 public DataSet (string dataSetName)
\r
84 this.dataSetName = dataSetName;
\r
85 tableCollection = new DataTableCollection (this);
\r
86 relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
\r
87 properties = new PropertyCollection ();
\r
88 prefix = String.Empty;
\r
91 protected DataSet (SerializationInfo info, StreamingContext context)
\r
94 GetSerializationData (info, context);
\r
97 #endregion // Constructors
\r
99 #region Public Properties
\r
101 [DataCategory ("Data")]
\r
103 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
\r
105 [DefaultValue (false)]
\r
106 public bool CaseSensitive {
\r
107 get { return caseSensitive; }
\r
109 caseSensitive = value;
\r
110 if (!caseSensitive) {
\r
111 foreach (DataTable table in Tables) {
\r
112 table.ResetCaseSensitiveIndexes ();
\r
113 foreach (Constraint c in table.Constraints)
\r
114 c.AssertConstraint ();
\r
117 foreach (DataTable table in Tables) {
\r
118 table.ResetCaseSensitiveIndexes ();
\r
124 [DataCategory ("Data")]
\r
126 [DataSysDescription ("The name of this DataSet.")]
\r
128 [DefaultValue ("")]
\r
129 public string DataSetName {
\r
130 get { return dataSetName; }
\r
131 set { dataSetName = value; }
\r
135 [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
137 [Browsable (false)]
\r
138 public DataViewManager DefaultViewManager {
\r
140 if (defaultView == null)
\r
141 defaultView = new DataViewManager (this);
\r
142 return defaultView;
\r
147 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
\r
149 [DefaultValue (true)]
\r
150 public bool EnforceConstraints {
\r
151 get { return enforceConstraints; }
\r
152 set { InternalEnforceConstraints (value, true); }
\r
155 [Browsable (false)]
\r
156 [DataCategory ("Data")]
\r
158 [DataSysDescription ("The collection that holds custom user information.")]
\r
160 public PropertyCollection ExtendedProperties {
\r
161 get { return properties; }
\r
164 [Browsable (false)]
\r
166 [DataSysDescription ("Indicates that the DataSet has errors.")]
\r
168 public bool HasErrors {
\r
170 for (int i = 0; i < Tables.Count; i++) {
\r
171 if (Tables[i].HasErrors)
\r
178 [DataCategory ("Data")]
\r
180 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
\r
182 public CultureInfo Locale {
\r
183 get { return locale != null ? locale : Thread.CurrentThread.CurrentCulture; }
\r
185 if (locale == null || !locale.Equals (value)) {
\r
186 // TODO: check if the new locale is valid
\r
187 // TODO: update locale of all tables
\r
193 internal bool LocaleSpecified {
\r
194 get { return locale != null; }
\r
197 internal void InternalEnforceConstraints (bool value,bool resetIndexes)
\r
199 if (value == enforceConstraints)
\r
203 if (resetIndexes) {
\r
204 // FIXME : is that correct?
\r
205 // By design the indexes should be updated at this point.
\r
206 // In Fill from BeginLoadData till EndLoadData indexes are not updated (reset in EndLoadData)
\r
207 // In DataRow.EndEdit indexes are always updated.
\r
208 foreach (DataTable table in Tables)
\r
209 table.ResetIndexes ();
\r
212 // TODO : Need to take care of Error handling and settting of RowErrors
\r
213 bool constraintViolated = false;
\r
214 foreach (DataTable table in Tables) {
\r
215 foreach (Constraint constraint in table.Constraints)
\r
216 constraint.AssertConstraint();
\r
217 table.AssertNotNullConstraints ();
\r
218 if (!constraintViolated && table.HasErrors)
\r
219 constraintViolated = true;
\r
222 if (constraintViolated)
\r
223 Constraint.ThrowConstraintException ();
\r
225 enforceConstraints = value;
\r
228 public void Merge (DataRow[] rows)
\r
230 Merge (rows, false, MissingSchemaAction.Add);
\r
233 public void Merge (DataSet dataSet)
\r
235 Merge (dataSet, false, MissingSchemaAction.Add);
\r
238 public void Merge (DataTable table)
\r
240 Merge (table, false, MissingSchemaAction.Add);
\r
243 public void Merge (DataSet dataSet, bool preserveChanges)
\r
245 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
\r
248 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
251 throw new ArgumentNullException ("rows");
\r
252 if (!IsLegalSchemaAction (missingSchemaAction))
\r
253 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
255 MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
\r
258 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
260 if (dataSet == null)
\r
261 throw new ArgumentNullException ("dataSet");
\r
262 if (!IsLegalSchemaAction (missingSchemaAction))
\r
263 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
265 MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
\r
268 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
271 throw new ArgumentNullException ("table");
\r
272 if (!IsLegalSchemaAction (missingSchemaAction))
\r
273 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
275 MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
\r
278 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
\r
280 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
\r
281 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
\r
286 [DataCategory ("Data")]
\r
288 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
\r
290 [DefaultValue ("")]
\r
291 public string Namespace {
\r
292 get { return _namespace; }
\r
294 //TODO - trigger an event if this happens?
\r
296 value = String.Empty;
\r
297 if (value != this._namespace)
\r
298 RaisePropertyChanging ("Namespace");
\r
299 _namespace = value;
\r
303 [DataCategory ("Data")]
\r
305 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
\r
307 [DefaultValue ("")]
\r
308 public string Prefix {
\r
309 get { return prefix; }
\r
312 value = String.Empty;
\r
313 // Prefix cannot contain any special characters other than '_' and ':'
\r
314 for (int i = 0; i < value.Length; i++) {
\r
315 if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
\r
316 throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
\r
319 if (value != this.prefix)
\r
320 RaisePropertyChanging ("Prefix");
\r
325 [DataCategory ("Data")]
\r
327 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
\r
329 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
\r
330 public DataRelationCollection Relations {
\r
331 get { return relationCollection; }
\r
334 [Browsable (false)]
\r
335 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
336 public override ISite Site {
\r
337 get { return base.Site; }
\r
338 set { base.Site = value; }
\r
341 [DataCategory ("Data")]
\r
343 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
\r
345 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
\r
346 public DataTableCollection Tables {
\r
347 get { return tableCollection; }
\r
350 #endregion // Public Properties
\r
352 #region Public Methods
\r
354 public void AcceptChanges ()
\r
356 foreach (DataTable tempTable in tableCollection)
\r
357 tempTable.AcceptChanges ();
\r
361 /// Clears all the tables
\r
363 public void Clear ()
\r
365 if (_xmlDataDocument != null)
\r
366 throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet.");
\r
367 bool enforceConstraints = this.EnforceConstraints;
\r
368 this.EnforceConstraints = false;
\r
369 for (int t = 0; t < tableCollection.Count; t++)
\r
370 tableCollection[t].Clear ();
\r
371 this.EnforceConstraints = enforceConstraints;
\r
374 public virtual DataSet Clone ()
\r
376 // need to return the same type as this...
\r
377 DataSet Copy = (DataSet) Activator.CreateInstance (GetType (), true);
\r
379 CopyProperties (Copy);
\r
381 foreach (DataTable Table in Tables) {
\r
382 // tables are often added in no-args constructor, don't add them
\r
384 if (!Copy.Tables.Contains (Table.TableName))
\r
385 Copy.Tables.Add (Table.Clone ());
\r
388 //Copy Relationships between tables after existance of tables
\r
389 //and setting properties correctly
\r
390 CopyRelations (Copy);
\r
395 // Copies both the structure and data for this DataSet.
\r
396 public DataSet Copy ()
\r
398 // need to return the same type as this...
\r
399 DataSet Copy = (DataSet) Activator.CreateInstance (GetType (), true);
\r
401 CopyProperties (Copy);
\r
403 // Copy DatSet's tables
\r
404 foreach (DataTable Table in Tables) {
\r
405 if (! Copy.Tables.Contains (Table.TableName)) {
\r
406 Copy.Tables.Add (Table.Copy ());
\r
409 foreach (DataRow row in Table.Rows)
\r
410 Copy.Tables [Table.TableName].ImportRow (row);
\r
413 //Copy Relationships between tables after existance of tables
\r
414 //and setting properties correctly
\r
415 CopyRelations (Copy);
\r
420 private void CopyProperties (DataSet Copy)
\r
422 Copy.CaseSensitive = CaseSensitive;
\r
423 //Copy.Container = Container
\r
424 Copy.DataSetName = DataSetName;
\r
425 //Copy.DefaultViewManager
\r
427 Copy.EnforceConstraints = EnforceConstraints;
\r
428 if(ExtendedProperties.Count > 0) {
\r
429 // Cannot copy extended properties directly as the property does not have a set accessor
\r
430 Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
\r
431 ExtendedProperties.Keys.CopyTo (tgtArray, 0);
\r
432 for (int i = 0; i < ExtendedProperties.Count; i++)
\r
433 Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
\r
435 Copy.locale = locale;
\r
436 Copy.Namespace = Namespace;
\r
437 Copy.Prefix = Prefix;
\r
438 //Copy.Site = Site; // FIXME : Not sure of this.
\r
442 private void CopyRelations (DataSet Copy)
\r
445 //Creation of the relation contains some of the properties, and the constructor
\r
446 //demands these values. instead changing the DataRelation constructor and behaviour the
\r
447 //parameters are pre-configured and sent to the most general constructor
\r
449 foreach (DataRelation MyRelation in this.Relations) {
\r
451 // typed datasets create relations through ctor.
\r
452 if (Copy.Relations.Contains (MyRelation.RelationName))
\r
455 string pTable = MyRelation.ParentTable.TableName;
\r
456 string cTable = MyRelation.ChildTable.TableName;
\r
457 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];
\r
458 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
\r
461 foreach (DataColumn DC in MyRelation.ParentColumns) {
\r
462 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
\r
468 foreach (DataColumn DC in MyRelation.ChildColumns) {
\r
469 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
\r
473 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC, false);
\r
474 Copy.Relations.Add (cRel);
\r
477 // Foreign Key constraints are not cloned in DataTable.Clone
\r
478 // so, these constraints should be cloned when copying the relations.
\r
479 foreach (DataTable table in this.Tables) {
\r
480 foreach (Constraint c in table.Constraints) {
\r
481 if (!(c is ForeignKeyConstraint)
\r
482 || Copy.Tables[table.TableName].Constraints.Contains (c.ConstraintName))
\r
484 ForeignKeyConstraint fc = (ForeignKeyConstraint)c;
\r
485 DataTable parentTable = Copy.Tables [fc.RelatedTable.TableName];
\r
486 DataTable currTable = Copy.Tables [table.TableName];
\r
487 DataColumn[] parentCols = new DataColumn [fc.RelatedColumns.Length];
\r
488 DataColumn[] childCols = new DataColumn [fc.Columns.Length];
\r
489 for (int j=0; j < parentCols.Length; ++j)
\r
490 parentCols [j] = parentTable.Columns[fc.RelatedColumns[j].ColumnName];
\r
491 for (int j=0; j < childCols.Length; ++j)
\r
492 childCols [j] = currTable.Columns[fc.Columns[j].ColumnName];
\r
493 currTable.Constraints.Add (fc.ConstraintName, parentCols, childCols);
\r
498 public DataSet GetChanges ()
\r
500 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
\r
504 public DataSet GetChanges (DataRowState rowStates)
\r
506 if (!HasChanges (rowStates))
\r
509 DataSet copySet = Clone ();
\r
510 bool prev = copySet.EnforceConstraints;
\r
511 copySet.EnforceConstraints = false;
\r
513 Hashtable addedRows = new Hashtable ();
\r
515 for (int i = 0; i < Tables.Count; i++) {
\r
516 DataTable origTable = Tables [i];
\r
517 DataTable copyTable = copySet.Tables[origTable.TableName];
\r
518 for (int j = 0; j < origTable.Rows.Count; j++) {
\r
519 DataRow row = origTable.Rows [j];
\r
520 if (!row.IsRowChanged (rowStates) || addedRows.Contains (row))
\r
522 AddChangedRow (addedRows, copyTable, row);
\r
525 copySet.EnforceConstraints = prev;
\r
529 private void AddChangedRow (Hashtable addedRows, DataTable copyTable, DataRow row)
\r
531 if (addedRows.ContainsKey (row))
\r
534 foreach (DataRelation relation in row.Table.ParentRelations) {
\r
535 DataRow parent = ( row.RowState != DataRowState.Deleted ?
\r
536 row.GetParentRow (relation) :
\r
537 row.GetParentRow (relation, DataRowVersion.Original)
\r
539 if (parent == null)
\r
541 // add the parent row
\r
542 DataTable parentCopyTable = copyTable.DataSet.Tables [parent.Table.TableName];
\r
543 AddChangedRow (addedRows, parentCopyTable, parent);
\r
546 // add the current row
\r
547 DataRow newRow = copyTable.NewNotInitializedRow ();
\r
548 copyTable.Rows.AddInternal (newRow);
\r
549 row.CopyValuesToRow (newRow);
\r
550 newRow.XmlRowID = row.XmlRowID;
\r
551 addedRows.Add (row, row);
\r
554 public string GetXml ()
\r
556 StringWriter Writer = new StringWriter ();
\r
557 WriteXml (Writer, XmlWriteMode.IgnoreSchema);
\r
558 return Writer.ToString ();
\r
561 public string GetXmlSchema ()
\r
563 StringWriter Writer = new StringWriter ();
\r
564 WriteXmlSchema (Writer);
\r
565 return Writer.ToString ();
\r
568 public bool HasChanges ()
\r
570 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
\r
573 public bool HasChanges (DataRowState rowStates)
\r
575 if (((int) rowStates & 0xffffffe0) != 0)
\r
576 throw new ArgumentOutOfRangeException ("rowStates");
\r
578 DataTableCollection tableCollection = Tables;
\r
580 DataRowCollection rowCollection;
\r
583 for (int i = 0; i < tableCollection.Count; i++) {
\r
584 table = tableCollection [i];
\r
585 rowCollection = table.Rows;
\r
586 for (int j = 0; j < rowCollection.Count; j++) {
\r
587 row = rowCollection [j];
\r
588 if ((row.RowState & rowStates) != 0)
\r
596 public void InferXmlSchema (XmlReader reader, string[] nsArray)
\r
598 if (reader == null)
\r
600 XmlDocument doc = new XmlDocument ();
\r
602 InferXmlSchema (doc, nsArray);
\r
605 private void InferXmlSchema (XmlDocument doc, string [] nsArray)
\r
607 XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
\r
610 public void InferXmlSchema (Stream stream, string[] nsArray)
\r
612 InferXmlSchema (new XmlTextReader (stream), nsArray);
\r
615 public void InferXmlSchema (TextReader reader, string[] nsArray)
\r
617 InferXmlSchema (new XmlTextReader (reader), nsArray);
\r
620 public void InferXmlSchema (string fileName, string[] nsArray)
\r
622 XmlTextReader reader = new XmlTextReader (fileName);
\r
624 InferXmlSchema (reader, nsArray);
\r
630 public virtual void RejectChanges ()
\r
633 bool oldEnforceConstraints = this.EnforceConstraints;
\r
634 this.EnforceConstraints = false;
\r
636 for (i = 0; i < this.Tables.Count;i++)
\r
637 this.Tables[i].RejectChanges ();
\r
639 this.EnforceConstraints = oldEnforceConstraints;
\r
642 public virtual void Reset ()
\r
644 // first we remove all ForeignKeyConstraints (if we will not do that
\r
645 // we will get an exception when clearing the tables).
\r
646 for (int i = 0; i < Tables.Count; i++) {
\r
647 ConstraintCollection cc = Tables[i].Constraints;
\r
648 for (int j = 0; j < cc.Count; j++) {
\r
649 if (cc[j] is ForeignKeyConstraint)
\r
655 Relations.Clear ();
\r
659 public void WriteXml (Stream stream)
\r
661 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
662 writer.Formatting = Formatting.Indented;
\r
667 /// Writes the current data for the DataSet to the specified file.
\r
669 /// <param name="filename">Fully qualified filename to write to</param>
\r
670 public void WriteXml (string fileName)
\r
672 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
673 writer.Formatting = Formatting.Indented;
\r
674 writer.WriteStartDocument (true);
\r
678 writer.WriteEndDocument ();
\r
683 public void WriteXml (TextWriter writer)
\r
685 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
686 xwriter.Formatting = Formatting.Indented;
\r
687 WriteXml (xwriter);
\r
690 public void WriteXml (XmlWriter writer)
\r
692 WriteXml (writer, XmlWriteMode.IgnoreSchema);
\r
695 public void WriteXml (string fileName, XmlWriteMode mode)
\r
697 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
698 writer.Formatting = Formatting.Indented;
\r
699 writer.WriteStartDocument (true);
\r
702 WriteXml (writer, mode);
\r
704 writer.WriteEndDocument ();
\r
709 public void WriteXml (Stream stream, XmlWriteMode mode)
\r
711 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
712 writer.Formatting = Formatting.Indented;
\r
713 WriteXml (writer, mode);
\r
716 public void WriteXml (TextWriter writer, XmlWriteMode mode)
\r
718 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
719 xwriter.Formatting = Formatting.Indented;
\r
720 WriteXml (xwriter, mode);
\r
723 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
\r
725 if (mode == XmlWriteMode.DiffGram) {
\r
727 WriteDiffGramElement(writer);
\r
730 // It should not write when there is no content to be written
\r
731 bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
\r
732 for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)
\r
733 shouldOutputContent = tableCollection [n].Rows.Count > 0;
\r
735 if (shouldOutputContent) {
\r
736 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
738 if (mode == XmlWriteMode.WriteSchema)
\r
739 DoWriteXmlSchema (writer);
\r
741 WriteTables (writer, mode, Tables, DataRowVersion.Default);
\r
742 writer.WriteEndElement ();
\r
745 if (mode == XmlWriteMode.DiffGram) {
\r
746 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
\r
747 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
\r
748 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
\r
749 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
\r
750 writer.WriteEndElement ();
\r
754 if (mode == XmlWriteMode.DiffGram)
\r
755 writer.WriteEndElement (); // diffgr:diffgram
\r
760 public void WriteXmlSchema (Stream stream)
\r
762 XmlTextWriter writer = new XmlTextWriter (stream, null );
\r
763 writer.Formatting = Formatting.Indented;
\r
764 WriteXmlSchema (writer);
\r
767 public void WriteXmlSchema (string fileName)
\r
769 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
771 writer.Formatting = Formatting.Indented;
\r
772 writer.WriteStartDocument (true);
\r
773 WriteXmlSchema (writer);
\r
775 writer.WriteEndDocument ();
\r
780 public void WriteXmlSchema (TextWriter writer)
\r
782 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
784 xwriter.Formatting = Formatting.Indented;
\r
785 WriteXmlSchema (xwriter);
\r
791 public void WriteXmlSchema (XmlWriter writer)
\r
793 //Create a skeleton doc and then write the schema
\r
794 //proper which is common to the WriteXml method in schema mode
\r
795 DoWriteXmlSchema (writer);
\r
798 public void ReadXmlSchema (Stream stream)
\r
800 XmlReader reader = new XmlTextReader (stream, null);
\r
801 ReadXmlSchema (reader);
\r
804 public void ReadXmlSchema (string fileName)
\r
806 XmlReader reader = new XmlTextReader (fileName);
\r
808 ReadXmlSchema (reader);
\r
814 public void ReadXmlSchema (TextReader reader)
\r
816 XmlReader xr = new XmlTextReader (reader);
\r
817 ReadXmlSchema (xr);
\r
820 public void ReadXmlSchema (XmlReader reader)
\r
823 new XmlSchemaDataImporter (this, reader, true).Process ();
\r
825 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
\r
826 SchemaMapper.Read (reader);
\r
830 public XmlReadMode ReadXml (Stream stream)
\r
832 return ReadXml (new XmlTextReader (stream));
\r
835 public XmlReadMode ReadXml (string fileName)
\r
837 XmlTextReader reader = new XmlTextReader (fileName);
\r
839 return ReadXml (reader);
\r
845 public XmlReadMode ReadXml (TextReader reader)
\r
847 return ReadXml (new XmlTextReader (reader));
\r
850 public XmlReadMode ReadXml (XmlReader reader)
\r
852 return ReadXml (reader, XmlReadMode.Auto);
\r
855 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
\r
857 return ReadXml (new XmlTextReader (stream), mode);
\r
860 public XmlReadMode ReadXml (string fileName, XmlReadMode mode)
\r
862 XmlTextReader reader = new XmlTextReader (fileName);
\r
864 return ReadXml (reader, mode);
\r
870 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
\r
872 return ReadXml (new XmlTextReader (reader), mode);
\r
875 // LAMESPEC: XmlReadMode.Fragment is far from presisely
\r
876 // documented. MS.NET infers schema against this mode.
\r
877 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
\r
879 if (reader == null)
\r
882 switch (reader.ReadState) {
\r
883 case ReadState.EndOfFile:
\r
884 case ReadState.Error:
\r
885 case ReadState.Closed:
\r
888 // Skip XML declaration and prolog
\r
889 reader.MoveToContent ();
\r
893 if (reader is XmlTextReader) {
\r
894 // we dont need whitespace
\r
895 ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.None;
\r
898 XmlDiffLoader DiffLoader = null;
\r
900 // If diffgram, then read the first element as diffgram
\r
901 if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
\r
903 case XmlReadMode.Auto:
\r
904 case XmlReadMode.DiffGram:
\r
905 if (DiffLoader == null)
\r
906 DiffLoader = new XmlDiffLoader (this);
\r
907 DiffLoader.Load (reader);
\r
908 // (and leave rest of the reader as is)
\r
909 return XmlReadMode.DiffGram;
\r
910 case XmlReadMode.Fragment:
\r
912 // (and continue to read)
\r
916 // (and leave rest of the reader as is)
\r
921 // If schema, then read the first element as schema
\r
922 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
924 case XmlReadMode.IgnoreSchema:
\r
925 case XmlReadMode.InferSchema:
\r
927 // (and break up read)
\r
929 case XmlReadMode.Fragment:
\r
930 ReadXmlSchema (reader);
\r
931 // (and continue to read)
\r
933 case XmlReadMode.Auto:
\r
934 if (Tables.Count == 0) {
\r
935 ReadXmlSchema (reader);
\r
936 return XmlReadMode.ReadSchema;
\r
938 // otherwise just ignore and return IgnoreSchema
\r
940 return XmlReadMode.IgnoreSchema;
\r
943 ReadXmlSchema (reader);
\r
944 // (and leave rest of the reader as is)
\r
945 return mode; // When DiffGram, return DiffGram
\r
952 int depth = (reader.NodeType == XmlNodeType.Element) ? reader.Depth : -1;
\r
954 XmlDocument doc = new XmlDocument ();
\r
955 XmlElement root = doc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
\r
956 if (reader.HasAttributes) {
\r
957 for (int i = 0; i < reader.AttributeCount; i++) {
\r
958 reader.MoveToAttribute(i);
\r
959 if (reader.NamespaceURI == XmlConstants.XmlnsNS)
\r
960 root.SetAttribute(reader.Name, reader.GetAttribute(i));
\r
962 XmlAttribute attr = root.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
\r
963 attr.Prefix = reader.Prefix;
\r
964 attr.Value = reader.GetAttribute(i);
\r
970 XmlReadMode retMode = mode;
\r
971 bool schemaLoaded = false;
\r
974 if( reader.Depth == depth ||
\r
975 reader.NodeType == XmlNodeType.EndElement)
\r
978 if (reader.NodeType != XmlNodeType.Element) {
\r
979 if (!reader.Read())
\r
984 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
986 case XmlReadMode.IgnoreSchema:
\r
987 case XmlReadMode.InferSchema:
\r
992 ReadXmlSchema (reader);
\r
993 retMode = XmlReadMode.ReadSchema;
\r
994 schemaLoaded = true;
\r
995 // (and leave rest of the reader as is)
\r
1002 if ((reader.LocalName == "diffgram") && (reader.NamespaceURI == XmlConstants.DiffgrNamespace)) {
\r
1003 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)
\r
1004 || mode == XmlReadMode.Auto) {
\r
1005 if (DiffLoader == null)
\r
1006 DiffLoader = new XmlDiffLoader (this);
\r
1007 DiffLoader.Load (reader);
\r
1008 // (and leave rest of the reader as is)
\r
1009 retMode = XmlReadMode.DiffGram;
\r
1018 XmlNode n = doc.ReadNode(reader);
\r
1019 root.AppendChild(n);
\r
1022 if (reader.NodeType == XmlNodeType.EndElement)
\r
1024 reader.MoveToContent();
\r
1026 if (mode == XmlReadMode.DiffGram) {
\r
1030 doc.AppendChild(root);
\r
1032 if (!schemaLoaded &&
\r
1033 retMode != XmlReadMode.ReadSchema &&
\r
1034 mode != XmlReadMode.IgnoreSchema &&
\r
1035 mode != XmlReadMode.Fragment &&
\r
1036 (Tables.Count == 0 || mode == XmlReadMode.InferSchema)) {
\r
1037 InferXmlSchema(doc, null);
\r
1038 if (mode == XmlReadMode.Auto)
\r
1039 retMode = XmlReadMode.InferSchema;
\r
1042 reader = new XmlNodeReader (doc);
\r
1043 XmlDataReader.ReadXml (this, reader, mode);
\r
1045 return retMode == XmlReadMode.Auto ?
\r
1046 XmlReadMode.IgnoreSchema : retMode;
\r
1048 #endregion // Public Methods
\r
1050 #region Public Events
\r
1052 [DataCategory ("Action")]
\r
1054 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
\r
1056 public event MergeFailedEventHandler MergeFailed;
\r
1058 #endregion // Public Events
\r
1060 #region IListSource methods
\r
1061 IList IListSource.GetList ()
\r
1063 return DefaultViewManager;
\r
1066 bool IListSource.ContainsListCollection {
\r
1071 #endregion IListSource methods
\r
1073 #region ISupportInitialize methods
\r
1075 internal bool InitInProgress {
\r
1076 get { return initInProgress; }
\r
1077 set { initInProgress = value; }
\r
1080 public void BeginInit ()
\r
1082 InitInProgress = true;
\r
1084 dataSetInitialized = false;
\r
1088 public void EndInit ()
\r
1090 // Finsh the init'ing the tables only after adding all the
\r
1091 // tables to the collection.
\r
1092 Tables.PostAddRange ();
\r
1093 for (int i=0; i < Tables.Count; ++i) {
\r
1094 if (!Tables [i].InitInProgress)
\r
1096 Tables [i].FinishInit ();
\r
1099 Relations.PostAddRange ();
\r
1100 InitInProgress = false;
\r
1102 dataSetInitialized = true;
\r
1103 DataSetInitialized ();
\r
1108 #region ISerializable
\r
1116 GetObjectData (SerializationInfo info, StreamingContext context)
\r
1119 if (RemotingFormat == SerializationFormat.Xml) {
\r
1121 StringWriter sw = new StringWriter ();
\r
1122 XmlTextWriter writer = new XmlTextWriter (sw);
\r
1123 DoWriteXmlSchema (writer);
\r
1125 info.AddValue ("XmlSchema", sw.ToString ());
\r
1127 sw = new StringWriter ();
\r
1128 writer = new XmlTextWriter (sw);
\r
1129 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1131 info.AddValue ("XmlDiffGram", sw.ToString ());
\r
1133 } else /*if (DataSet.RemotingFormat == SerializationFormat.Binary)*/ {
\r
1134 BinarySerialize (info);
\r
1140 #region Protected Methods
\r
1141 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
\r
1144 if (IsBinarySerialized (info, context)) {
\r
1145 BinaryDeserialize (info);
\r
1149 string s = info.GetValue ("XmlSchema", typeof (String)) as String;
\r
1150 XmlTextReader reader = new XmlTextReader (new StringReader (s));
\r
1151 ReadXmlSchema (reader);
\r
1154 s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
\r
1155 reader = new XmlTextReader (new StringReader (s));
\r
1156 ReadXml (reader, XmlReadMode.DiffGram);
\r
1161 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
\r
1166 protected virtual void ReadXmlSerializable (XmlReader reader)
\r
1168 ReadXml (reader, XmlReadMode.DiffGram);
\r
1171 void IXmlSerializable.ReadXml (XmlReader reader)
\r
1173 ReadXmlSerializable(reader);
\r
1176 void IXmlSerializable.WriteXml (XmlWriter writer)
\r
1178 DoWriteXmlSchema (writer);
\r
1179 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1182 XmlSchema IXmlSerializable.GetSchema ()
\r
1184 if (GetType() == typeof(DataSet))
\r
1186 MemoryStream stream = new MemoryStream();
\r
1187 XmlTextWriter writer = new XmlTextWriter(stream, null);
\r
1188 WriteXmlSchema(writer);
\r
1189 stream.Position = 0;
\r
1190 return XmlSchema.Read(new XmlTextReader(stream), (ValidationEventHandler)null);
\r
1193 protected virtual bool ShouldSerializeRelations ()
\r
1198 protected virtual bool ShouldSerializeTables ()
\r
1204 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
\r
1206 throw new NotImplementedException ();
\r
1210 protected virtual void OnRemoveRelation (DataRelation relation)
\r
1212 throw new NotImplementedException ();
\r
1216 protected virtual void OnRemoveTable (DataTable table)
\r
1218 throw new NotImplementedException ();
\r
1221 internal virtual void OnMergeFailed (MergeFailedEventArgs e)
\r
1223 if (MergeFailed != null)
\r
1224 MergeFailed (this, e);
\r
1226 throw new DataException (e.Conflict);
\r
1230 protected internal void RaisePropertyChanging (string name)
\r
1236 #region Private Methods
\r
1238 internal static string WriteObjectXml (object o)
\r
1240 switch (Type.GetTypeCode (o.GetType ())) {
\r
1241 case TypeCode.Boolean:
\r
1242 return XmlConvert.ToString ((Boolean) o);
\r
1243 case TypeCode.Byte:
\r
1244 return XmlConvert.ToString ((Byte) o);
\r
1245 case TypeCode.Char:
\r
1246 return XmlConvert.ToString ((Char) o);
\r
1247 case TypeCode.DateTime:
\r
1249 return XmlConvert.ToString ((DateTime) o, XmlDateTimeSerializationMode.Unspecified);
\r
1251 return XmlConvert.ToString ((DateTime) o);
\r
1253 case TypeCode.Decimal:
\r
1254 return XmlConvert.ToString ((Decimal) o);
\r
1255 case TypeCode.Double:
\r
1256 return XmlConvert.ToString ((Double) o);
\r
1257 case TypeCode.Int16:
\r
1258 return XmlConvert.ToString ((Int16) o);
\r
1259 case TypeCode.Int32:
\r
1260 return XmlConvert.ToString ((Int32) o);
\r
1261 case TypeCode.Int64:
\r
1262 return XmlConvert.ToString ((Int64) o);
\r
1263 case TypeCode.SByte:
\r
1264 return XmlConvert.ToString ((SByte) o);
\r
1265 case TypeCode.Single:
\r
1266 return XmlConvert.ToString ((Single) o);
\r
1267 case TypeCode.UInt16:
\r
1268 return XmlConvert.ToString ((UInt16) o);
\r
1269 case TypeCode.UInt32:
\r
1270 return XmlConvert.ToString ((UInt32) o);
\r
1271 case TypeCode.UInt64:
\r
1272 return XmlConvert.ToString ((UInt64) o);
\r
1274 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
\r
1275 if (o is Guid) return XmlConvert.ToString ((Guid) o);
\r
1276 if (o is byte[]) return Convert.ToBase64String ((byte[])o);
\r
1278 return o.ToString ();
\r
1281 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
\r
1283 //WriteTable takes care of skipping a table if it has a
\r
1284 //Nested Parent Relationship
\r
1285 foreach (DataTable table in tableCollection)
\r
1286 WriteTable ( writer, table, mode, version);
\r
1289 internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
\r
1291 DataRow[] rows = table.NewRowArray(table.Rows.Count);
\r
1292 table.Rows.CopyTo (rows, 0);
\r
1293 WriteTable (writer, rows, mode, version, true);
\r
1296 internal static void WriteTable (XmlWriter writer,
\r
1298 XmlWriteMode mode,
\r
1299 DataRowVersion version, bool skipIfNested)
\r
1301 if (rows.Length == 0) return;
\r
1302 DataTable table = rows[0].Table;
\r
1304 if (table.TableName == null || table.TableName == "")
\r
1305 throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");
\r
1307 //The columns can be attributes, hidden, elements, or simple content
\r
1308 //There can be 0-1 simple content cols or 0-* elements
\r
1309 System.Collections.ArrayList atts;
\r
1310 System.Collections.ArrayList elements;
\r
1311 DataColumn simple = null;
\r
1313 SplitColumns (table, out atts, out elements, out simple);
\r
1314 //sort out the namespacing
\r
1315 int relationCount = table.ParentRelations.Count;
\r
1317 foreach (DataRow row in rows) {
\r
1318 if (skipIfNested) {
\r
1319 // Skip rows that is a child of any tables.
\r
1320 bool skip = false;
\r
1321 for (int i = 0; i < table.ParentRelations.Count; i++) {
\r
1322 DataRelation prel = table.ParentRelations [i];
\r
1325 if (row.GetParentRow (prel) != null) {
\r
1334 if (!row.HasVersion(version) ||
\r
1335 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
\r
1336 && version == DataRowVersion.Original))
\r
1339 // First check are all the rows null. If they are we just write empty element
\r
1340 bool AllNulls = true;
\r
1341 foreach (DataColumn dc in table.Columns) {
\r
1342 if (row [dc.ColumnName, version] != DBNull.Value) {
\r
1348 // If all of the columns were null, we have to write empty element
\r
1350 writer.WriteElementString (XmlHelper.Encode (table.TableName), "");
\r
1354 WriteTableElement (writer, mode, table, row, version);
\r
1356 foreach (DataColumn col in atts)
\r
1357 WriteColumnAsAttribute (writer, mode, col, row, version);
\r
1359 if (simple != null) {
\r
1360 writer.WriteString (WriteObjectXml (row[simple, version]));
\r
1362 foreach (DataColumn col in elements)
\r
1363 WriteColumnAsElement (writer, mode, col, row, version);
\r
1366 foreach (DataRelation relation in table.ChildRelations) {
\r
1367 if (relation.Nested)
\r
1368 WriteTable (writer, row.GetChildRows (relation), mode, version, false);
\r
1371 writer.WriteEndElement ();
\r
1376 internal static void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
\r
1378 string colnspc = null;
\r
1379 object rowObject = row [col, version];
\r
1381 if (rowObject == null || rowObject == DBNull.Value)
\r
1384 if (col.Namespace != String.Empty)
\r
1385 colnspc = col.Namespace;
\r
1387 //TODO check if I can get away with write element string
\r
1388 WriteStartElement (writer, mode, colnspc, col.Prefix, XmlHelper.Encode (col.ColumnName));
\r
1389 if (typeof (IXmlSerializable).IsAssignableFrom (col.DataType)) {
\r
1390 ((IXmlSerializable)rowObject).WriteXml (writer);
\r
1392 writer.WriteString (WriteObjectXml (rowObject));
\r
1395 writer.WriteEndElement ();
\r
1398 internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
\r
1400 if (!row.IsNull (col))
\r
1401 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));
\r
1404 internal static void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
\r
1406 //sort out the namespacing
\r
1407 string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;
\r
1409 WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));
\r
1411 if (mode == XmlWriteMode.DiffGram) {
\r
1412 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
\r
1413 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));
\r
1414 string modeName = null;
\r
1415 if (row.RowState == DataRowState.Modified)
\r
1416 modeName = "modified";
\r
1417 else if (row.RowState == DataRowState.Added)
\r
1418 modeName = "inserted";
\r
1420 if (version != DataRowVersion.Original && modeName != null)
\r
1421 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
\r
1425 internal static void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
\r
1427 writer.WriteStartElement (prefix, name, nspc);
\r
1430 internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
\r
1433 // case XmlWriteMode.WriteSchema:
\r
1434 // writer.WriteAttributeString (prefix, name, nspc);
\r
1436 case XmlWriteMode.DiffGram:
\r
1437 writer.WriteAttributeString (prefix, name, nspc,stringValue);
\r
1440 writer.WriteAttributeString (name, stringValue);
\r
1445 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
\r
1447 if (mode == XmlWriteMode.DiffGram) {
\r
1448 table.SetRowsID ();
\r
1449 WriteDiffGramElement (writer);
\r
1452 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
1454 WriteTable (writer, table, mode, DataRowVersion.Default);
\r
1456 if (mode == XmlWriteMode.DiffGram) {
\r
1457 writer.WriteEndElement (); //DataSet name
\r
1458 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
\r
1460 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
\r
1461 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
\r
1462 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
\r
1463 writer.WriteEndElement ();
\r
1466 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
\r
1469 private void DoWriteXmlSchema (XmlWriter writer)
\r
1471 if (writer.WriteState == WriteState.Start)
\r
1472 writer.WriteStartDocument ();
\r
1473 XmlSchemaWriter.WriteXmlSchema (this, writer);
\r
1477 /// Helper function to split columns into attributes elements and simple
\r
1480 internal static void SplitColumns (DataTable table,
\r
1481 out ArrayList atts,
\r
1482 out ArrayList elements,
\r
1483 out DataColumn simple)
\r
1485 //The columns can be attributes, hidden, elements, or simple content
\r
1486 //There can be 0-1 simple content cols or 0-* elements
\r
1487 atts = new System.Collections.ArrayList ();
\r
1488 elements = new System.Collections.ArrayList ();
\r
1491 //Sort out the columns
\r
1492 foreach (DataColumn col in table.Columns) {
\r
1493 switch (col.ColumnMapping) {
\r
1494 case MappingType.Attribute:
\r
1497 case MappingType.Element:
\r
1498 elements.Add (col);
\r
1500 case MappingType.SimpleContent:
\r
1501 if (simple != null) {
\r
1502 throw new System.InvalidOperationException ("There may only be one simple content element");
\r
1507 //ignore Hidden elements
\r
1513 internal static void WriteDiffGramElement (XmlWriter writer)
\r
1515 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
\r
1516 WriteAttributeString (writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
\r
1519 private void SetRowsID ()
\r
1521 foreach (DataTable table in Tables)
\r
1522 table.SetRowsID ();
\r
1525 #endregion //Private Xml Serialisation
\r
1529 [XmlSchemaProvider ("GetDataSetSchema")]
\r
1530 [XmlRoot ("DataSet")]
\r
1531 partial class DataSet : ISupportInitializeNotification {
\r
1532 private bool dataSetInitialized = true;
\r
1533 public event EventHandler Initialized;
\r
1536 protected DataSet (SerializationInfo info, StreamingContext context, bool constructSchema)
\r
1537 : this (info, context)
\r
1541 SerializationFormat remotingFormat = SerializationFormat.Xml;
\r
1542 [DefaultValue (SerializationFormat.Xml)]
\r
1543 public SerializationFormat RemotingFormat {
\r
1544 get { return remotingFormat; }
\r
1545 set { remotingFormat = value; }
\r
1548 [Browsable (false)]
\r
1549 public bool IsInitialized {
\r
1550 get { return dataSetInitialized; }
\r
1553 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
1554 [Browsable (false)]
\r
1555 public virtual SchemaSerializationMode SchemaSerializationMode {
\r
1556 get { return SchemaSerializationMode.IncludeSchema; }
\r
1558 if (value != SchemaSerializationMode.IncludeSchema)
\r
1559 throw new InvalidOperationException (
\r
1560 "Only IncludeSchema Mode can be set for Untyped DataSet");
\r
1564 public DataTableReader CreateDataReader (params DataTable[] dataTables)
\r
1566 return new DataTableReader (dataTables);
\r
1569 public DataTableReader CreateDataReader ()
\r
1571 return new DataTableReader ((DataTable[])Tables.ToArray (typeof (DataTable)));
\r
1574 public static XmlSchemaComplexType GetDataSetSchema (XmlSchemaSet schemaSet)
\r
1576 return new XmlSchemaComplexType ();
\r
1579 public void Load (IDataReader reader, LoadOption loadOption, params DataTable[] tables)
\r
1581 if (reader == null)
\r
1582 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1584 foreach (DataTable dt in tables) {
\r
1585 if (dt.DataSet == null || dt.DataSet != this)
\r
1586 throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");
\r
1587 dt.Load (reader, loadOption);
\r
1588 reader.NextResult ();
\r
1592 public void Load (IDataReader reader, LoadOption loadOption, params string[] tables)
\r
1594 if (reader == null)
\r
1595 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1597 foreach (string tableName in tables) {
\r
1598 DataTable dt = Tables [tableName];
\r
1601 dt = new DataTable (tableName);
\r
1604 dt.Load (reader, loadOption);
\r
1605 reader.NextResult ();
\r
1609 public virtual void Load (IDataReader reader, LoadOption loadOption,
\r
1610 FillErrorEventHandler errorHandler, params DataTable[] tables)
\r
1612 if (reader == null)
\r
1613 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1615 foreach (DataTable dt in tables) {
\r
1616 if (dt.DataSet == null || dt.DataSet != this)
\r
1617 throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");
\r
1618 dt.Load (reader, loadOption, errorHandler);
\r
1619 reader.NextResult ();
\r
1623 void BinarySerialize (SerializationInfo si)
\r
1625 Version vr = new Version(2, 0);
\r
1626 si.AddValue ("DataSet.RemotingVersion", vr, typeof (Version));
\r
1627 si.AddValue ("DataSet.RemotingFormat", RemotingFormat, typeof (SerializationFormat));
\r
1628 si.AddValue ("DataSet.DataSetName", DataSetName);
\r
1629 si.AddValue ("DataSet.Namespace", Namespace);
\r
1630 si.AddValue ("DataSet.Prefix", Prefix);
\r
1631 si.AddValue ("DataSet.CaseSensitive", CaseSensitive);
\r
1632 si.AddValue ("DataSet.LocaleLCID", Locale.LCID);
\r
1633 si.AddValue ("DataSet.EnforceConstraints", EnforceConstraints);
\r
1634 si.AddValue ("DataSet.ExtendedProperties", properties, typeof (PropertyCollection));
\r
1636 Tables.BinarySerialize_Schema (si);
\r
1637 Tables.BinarySerialize_Data (si);
\r
1639 Relations.BinarySerialize (si);
\r
1642 void BinaryDeserialize (SerializationInfo info)
\r
1644 ArrayList arrayList = null;
\r
1646 DataSetName = info.GetString ("DataSet.DataSetName");
\r
1647 Namespace = info.GetString ("DataSet.Namespace");
\r
1648 CaseSensitive = info.GetBoolean ("DataSet.CaseSensitive");
\r
1649 Locale = new CultureInfo (info.GetInt32 ("DataSet.LocaleLCID"));
\r
1650 EnforceConstraints = info.GetBoolean ("DataSet.EnforceConstraints");
\r
1651 Prefix = info.GetString ("DataSet.Prefix");
\r
1653 FIXME: Private variable available in SerializationInfo
\r
1654 this.RemotingVersion = (System.Version) info.GetValue("DataSet.RemotingVersion",
\r
1655 typeof(System.Version));
\r
1657 properties = (PropertyCollection) info.GetValue ("DataSet.ExtendedProperties",
\r
1658 typeof (PropertyCollection));
\r
1659 int tableCount = info.GetInt32 ("DataSet.Tables.Count");
\r
1662 DataTable dt = null;
\r
1663 for (int i = 0; i < tableCount; i++) {
\r
1664 bytes = (Byte []) info.GetValue ("DataSet.Tables_" + i,
\r
1666 MemoryStream ms = new MemoryStream (bytes);
\r
1667 BinaryFormatter bf = new BinaryFormatter ();
\r
1668 dt = (DataTable) bf.Deserialize (ms);
\r
1670 for (int j = 0; j < dt.Columns.Count; j++) {
\r
1671 dt.Columns[j].Expression = info.GetString ("DataTable_" + i +
\r
1672 ".DataColumn_" + j +
\r
1677 int rowsCount = info.GetInt32 ("DataTable_" + i + ".Rows.Count");
\r
1678 int recordsCount = info.GetInt32 ("DataTable_" + i + ".Records.Count");
\r
1680 ArrayList nullBits = (ArrayList) info.GetValue ("DataTable_" + i + ".NullBits",
\r
1681 typeof (ArrayList));
\r
1682 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Records",
\r
1683 typeof (ArrayList));
\r
1684 BitArray rowStateBitArray = (BitArray) info.GetValue ("DataTable_" + i + ".RowStates",
\r
1685 typeof (BitArray));
\r
1686 dt.DeserializeRecords (arrayList, nullBits, rowStateBitArray);
\r
1689 for (int i = 0; i < tableCount; i++) {
\r
1691 dt.dataSet = this;
\r
1692 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Constraints",
\r
1693 typeof (ArrayList));
\r
1694 if (dt.Constraints == null)
\r
1695 dt.Constraints = new ConstraintCollection (dt);
\r
1696 dt.DeserializeConstraints (arrayList);
\r
1698 arrayList = (ArrayList) info.GetValue ("DataSet.Relations",
\r
1699 typeof (ArrayList));
\r
1700 bool bParentColumn = true;
\r
1701 for (int l = 0; l < arrayList.Count; l++) {
\r
1702 ArrayList tmpArrayList = (ArrayList) arrayList[l];
\r
1703 ArrayList childColumns = new ArrayList ();
\r
1704 ArrayList parentColumns = new ArrayList ();
\r
1705 for (int k = 0; k < tmpArrayList.Count; k++) {
\r
1706 if (tmpArrayList[k] != null && typeof (int) == tmpArrayList[k].GetType().GetElementType()) {
\r
1707 Array dataColumnArray = (Array)tmpArrayList[k];
\r
1708 if (bParentColumn) {
\r
1709 parentColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].
\r
1710 Columns [(int) dataColumnArray.GetValue (1)]);
\r
1711 bParentColumn = false;
\r
1714 childColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].
\r
1715 Columns [(int) dataColumnArray.GetValue (1)]);
\r
1716 bParentColumn = true;
\r
1720 Relations.Add ((string) tmpArrayList [0],
\r
1721 (DataColumn []) parentColumns.ToArray (typeof (DataColumn)),
\r
1722 (DataColumn []) childColumns.ToArray (typeof (DataColumn)),
\r
1727 private void OnDataSetInitialized (EventArgs e)
\r
1729 if (null != Initialized)
\r
1730 Initialized (this, e);
\r
1733 private void DataSetInitialized ()
\r
1735 EventArgs e = new EventArgs ();
\r
1736 OnDataSetInitialized (e);
\r
1740 protected virtual void InitializeDerivedDataSet ()
\r
1742 throw new NotImplementedException ();
\r
1745 protected SchemaSerializationMode DetermineSchemaSerializationMode (XmlReader reader)
\r
1747 return SchemaSerializationMode.IncludeSchema;
\r
1750 protected SchemaSerializationMode DetermineSchemaSerializationMode (SerializationInfo info, StreamingContext context)
\r
1752 return SchemaSerializationMode.IncludeSchema;
\r
1755 protected bool IsBinarySerialized (SerializationInfo info, StreamingContext context)
\r
1757 SerializationInfoEnumerator e = info.GetEnumerator ();
\r
1758 while (e.MoveNext ()) {
\r
1759 if (e.ObjectType == typeof (System.Data.SerializationFormat))
\r