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
75 internal TableAdapterSchemaInfo tableAdapterSchemaInfo;
\r
77 bool initInProgress;
\r
79 #region Constructors
\r
82 : this ("NewDataSet")
\r
86 public DataSet (string dataSetName)
\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
95 protected DataSet (SerializationInfo info, StreamingContext context)
\r
99 if (IsBinarySerialized (info, context)) {
\r
100 BinaryDeserialize (info);
\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
109 GetSerializationData (info, context);
\r
112 #endregion // Constructors
\r
114 #region Public Properties
\r
116 [DataCategory ("Data")]
\r
118 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
\r
120 [DefaultValue (false)]
\r
121 public bool CaseSensitive {
\r
122 get { return caseSensitive; }
\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
132 foreach (DataTable table in Tables) {
\r
133 table.ResetCaseSensitiveIndexes ();
\r
139 [DataCategory ("Data")]
\r
141 [DataSysDescription ("The name of this DataSet.")]
\r
143 [DefaultValue ("")]
\r
144 public string DataSetName {
\r
145 get { return dataSetName; }
\r
146 set { dataSetName = value; }
\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
152 [Browsable (false)]
\r
153 public DataViewManager DefaultViewManager {
\r
155 if (defaultView == null)
\r
156 defaultView = new DataViewManager (this);
\r
157 return defaultView;
\r
162 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
\r
164 [DefaultValue (true)]
\r
165 public bool EnforceConstraints {
\r
166 get { return enforceConstraints; }
\r
167 set { InternalEnforceConstraints (value, true); }
\r
170 [Browsable (false)]
\r
171 [DataCategory ("Data")]
\r
173 [DataSysDescription ("The collection that holds custom user information.")]
\r
175 public PropertyCollection ExtendedProperties {
\r
176 get { return properties; }
\r
179 [Browsable (false)]
\r
181 [DataSysDescription ("Indicates that the DataSet has errors.")]
\r
183 public bool HasErrors {
\r
185 for (int i = 0; i < Tables.Count; i++) {
\r
186 if (Tables[i].HasErrors)
\r
193 [DataCategory ("Data")]
\r
195 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
\r
197 public CultureInfo Locale {
\r
198 get { return locale != null ? locale : Thread.CurrentThread.CurrentCulture; }
\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
208 internal bool LocaleSpecified {
\r
209 get { return locale != null; }
\r
214 internal TableAdapterSchemaInfo TableAdapterSchemaData {
\r
215 get { return tableAdapterSchemaInfo; }
\r
219 internal void InternalEnforceConstraints (bool value,bool resetIndexes)
\r
221 if (value == enforceConstraints)
\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
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
244 if (constraintViolated)
\r
245 Constraint.ThrowConstraintException ();
\r
247 enforceConstraints = value;
\r
250 public void Merge (DataRow[] rows)
\r
252 Merge (rows, false, MissingSchemaAction.Add);
\r
255 public void Merge (DataSet dataSet)
\r
257 Merge (dataSet, false, MissingSchemaAction.Add);
\r
260 public void Merge (DataTable table)
\r
262 Merge (table, false, MissingSchemaAction.Add);
\r
265 public void Merge (DataSet dataSet, bool preserveChanges)
\r
267 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
\r
270 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
273 throw new ArgumentNullException ("rows");
\r
274 if (!IsLegalSchemaAction (missingSchemaAction))
\r
275 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
277 MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
\r
280 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
282 if (dataSet == null)
\r
283 throw new ArgumentNullException ("dataSet");
\r
284 if (!IsLegalSchemaAction (missingSchemaAction))
\r
285 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
287 MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
\r
290 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
\r
293 throw new ArgumentNullException ("table");
\r
294 if (!IsLegalSchemaAction (missingSchemaAction))
\r
295 throw new ArgumentOutOfRangeException ("missingSchemaAction");
\r
297 MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
\r
300 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
\r
302 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
\r
303 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
\r
308 [DataCategory ("Data")]
\r
310 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
\r
312 [DefaultValue ("")]
\r
313 public string Namespace {
\r
314 get { return _namespace; }
\r
316 //TODO - trigger an event if this happens?
\r
318 value = String.Empty;
\r
319 if (value != this._namespace)
\r
320 RaisePropertyChanging ("Namespace");
\r
321 _namespace = value;
\r
325 [DataCategory ("Data")]
\r
327 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
\r
329 [DefaultValue ("")]
\r
330 public string Prefix {
\r
331 get { return prefix; }
\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
341 if (value != this.prefix)
\r
342 RaisePropertyChanging ("Prefix");
\r
347 [DataCategory ("Data")]
\r
349 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
\r
351 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
\r
352 public DataRelationCollection Relations {
\r
353 get { return relationCollection; }
\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
363 [DataCategory ("Data")]
\r
365 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
\r
367 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
\r
368 public DataTableCollection Tables {
\r
369 get { return tableCollection; }
\r
372 #endregion // Public Properties
\r
374 #region Public Methods
\r
376 public void AcceptChanges ()
\r
378 foreach (DataTable tempTable in tableCollection)
\r
379 tempTable.AcceptChanges ();
\r
383 /// Clears all the tables
\r
385 public void Clear ()
\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
396 public virtual DataSet Clone ()
\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 foreach (DataTable Table in Tables) {
\r
404 // tables are often added in no-args constructor, don't add them
\r
406 if (!Copy.Tables.Contains (Table.TableName))
\r
407 Copy.Tables.Add (Table.Clone ());
\r
410 //Copy Relationships between tables after existance of tables
\r
411 //and setting properties correctly
\r
412 CopyRelations (Copy);
\r
417 // Copies both the structure and data for this DataSet.
\r
418 public DataSet Copy ()
\r
420 // need to return the same type as this...
\r
421 DataSet Copy = (DataSet) Activator.CreateInstance (GetType (), true);
\r
423 CopyProperties (Copy);
\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
431 foreach (DataRow row in Table.Rows)
\r
432 Copy.Tables [Table.TableName].ImportRow (row);
\r
435 //Copy Relationships between tables after existance of tables
\r
436 //and setting properties correctly
\r
437 CopyRelations (Copy);
\r
442 private void CopyProperties (DataSet Copy)
\r
444 Copy.CaseSensitive = CaseSensitive;
\r
445 //Copy.Container = Container
\r
446 Copy.DataSetName = DataSetName;
\r
447 //Copy.DefaultViewManager
\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
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
464 private void CopyRelations (DataSet Copy)
\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
471 foreach (DataRelation MyRelation in this.Relations) {
\r
473 // typed datasets create relations through ctor.
\r
474 if (Copy.Relations.Contains (MyRelation.RelationName))
\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
483 foreach (DataColumn DC in MyRelation.ParentColumns) {
\r
484 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
\r
490 foreach (DataColumn DC in MyRelation.ChildColumns) {
\r
491 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
\r
495 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC, false);
\r
496 Copy.Relations.Add (cRel);
\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
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
520 public DataSet GetChanges ()
\r
522 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
\r
526 public DataSet GetChanges (DataRowState rowStates)
\r
528 if (!HasChanges (rowStates))
\r
531 DataSet copySet = Clone ();
\r
532 bool prev = copySet.EnforceConstraints;
\r
533 copySet.EnforceConstraints = false;
\r
535 Hashtable addedRows = new Hashtable ();
\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
544 AddChangedRow (addedRows, copyTable, row);
\r
547 copySet.EnforceConstraints = prev;
\r
551 private void AddChangedRow (Hashtable addedRows, DataTable copyTable, DataRow row)
\r
553 if (addedRows.ContainsKey (row))
\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
561 if (parent == null)
\r
563 // add the parent row
\r
564 DataTable parentCopyTable = copyTable.DataSet.Tables [parent.Table.TableName];
\r
565 AddChangedRow (addedRows, parentCopyTable, parent);
\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
576 public string GetXml ()
\r
578 StringWriter Writer = new StringWriter ();
\r
579 WriteXml (Writer, XmlWriteMode.IgnoreSchema);
\r
580 return Writer.ToString ();
\r
583 public string GetXmlSchema ()
\r
585 StringWriter Writer = new StringWriter ();
\r
586 WriteXmlSchema (Writer);
\r
587 return Writer.ToString ();
\r
590 public bool HasChanges ()
\r
592 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
\r
595 public bool HasChanges (DataRowState rowStates)
\r
597 if (((int) rowStates & 0xffffffe0) != 0)
\r
598 throw new ArgumentOutOfRangeException ("rowStates");
\r
600 DataTableCollection tableCollection = Tables;
\r
602 DataRowCollection rowCollection;
\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
618 public void InferXmlSchema (XmlReader reader, string[] nsArray)
\r
620 if (reader == null)
\r
622 XmlDocument doc = new XmlDocument ();
\r
624 InferXmlSchema (doc, nsArray);
\r
627 private void InferXmlSchema (XmlDocument doc, string [] nsArray)
\r
629 XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
\r
632 public void InferXmlSchema (Stream stream, string[] nsArray)
\r
634 InferXmlSchema (new XmlTextReader (stream), nsArray);
\r
637 public void InferXmlSchema (TextReader reader, string[] nsArray)
\r
639 InferXmlSchema (new XmlTextReader (reader), nsArray);
\r
642 public void InferXmlSchema (string fileName, string[] nsArray)
\r
644 XmlTextReader reader = new XmlTextReader (fileName);
\r
646 InferXmlSchema (reader, nsArray);
\r
652 public virtual void RejectChanges ()
\r
655 bool oldEnforceConstraints = this.EnforceConstraints;
\r
656 this.EnforceConstraints = false;
\r
658 for (i = 0; i < this.Tables.Count;i++)
\r
659 this.Tables[i].RejectChanges ();
\r
661 this.EnforceConstraints = oldEnforceConstraints;
\r
664 public virtual void Reset ()
\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
677 Relations.Clear ();
\r
681 public void WriteXml (Stream stream)
\r
683 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
684 writer.Formatting = Formatting.Indented;
\r
689 /// Writes the current data for the DataSet to the specified file.
\r
691 /// <param name="filename">Fully qualified filename to write to</param>
\r
692 public void WriteXml (string fileName)
\r
694 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
695 writer.Formatting = Formatting.Indented;
\r
696 writer.WriteStartDocument (true);
\r
700 writer.WriteEndDocument ();
\r
705 public void WriteXml (TextWriter writer)
\r
707 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
708 xwriter.Formatting = Formatting.Indented;
\r
709 WriteXml (xwriter);
\r
712 public void WriteXml (XmlWriter writer)
\r
714 WriteXml (writer, XmlWriteMode.IgnoreSchema);
\r
717 public void WriteXml (string fileName, XmlWriteMode mode)
\r
719 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
720 writer.Formatting = Formatting.Indented;
\r
721 writer.WriteStartDocument (true);
\r
724 WriteXml (writer, mode);
\r
726 writer.WriteEndDocument ();
\r
731 public void WriteXml (Stream stream, XmlWriteMode mode)
\r
733 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
734 writer.Formatting = Formatting.Indented;
\r
735 WriteXml (writer, mode);
\r
738 public void WriteXml (TextWriter writer, XmlWriteMode mode)
\r
740 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
741 xwriter.Formatting = Formatting.Indented;
\r
742 WriteXml (xwriter, mode);
\r
745 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
\r
747 if (mode == XmlWriteMode.DiffGram) {
\r
749 WriteDiffGramElement(writer);
\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
757 if (shouldOutputContent) {
\r
758 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
760 if (mode == XmlWriteMode.WriteSchema)
\r
761 DoWriteXmlSchema (writer);
\r
763 WriteTables (writer, mode, Tables, DataRowVersion.Default);
\r
764 writer.WriteEndElement ();
\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
776 if (mode == XmlWriteMode.DiffGram)
\r
777 writer.WriteEndElement (); // diffgr:diffgram
\r
782 public void WriteXmlSchema (Stream stream)
\r
784 XmlTextWriter writer = new XmlTextWriter (stream, null );
\r
785 writer.Formatting = Formatting.Indented;
\r
786 WriteXmlSchema (writer);
\r
789 public void WriteXmlSchema (string fileName)
\r
791 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
793 writer.Formatting = Formatting.Indented;
\r
794 writer.WriteStartDocument (true);
\r
795 WriteXmlSchema (writer);
\r
797 writer.WriteEndDocument ();
\r
802 public void WriteXmlSchema (TextWriter writer)
\r
804 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
806 xwriter.Formatting = Formatting.Indented;
\r
807 WriteXmlSchema (xwriter);
\r
813 public void WriteXmlSchema (XmlWriter writer)
\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
820 public void ReadXmlSchema (Stream stream)
\r
822 XmlReader reader = new XmlTextReader (stream, null);
\r
823 ReadXmlSchema (reader);
\r
826 public void ReadXmlSchema (string fileName)
\r
828 XmlReader reader = new XmlTextReader (fileName);
\r
830 ReadXmlSchema (reader);
\r
836 public void ReadXmlSchema (TextReader reader)
\r
838 XmlReader xr = new XmlTextReader (reader);
\r
839 ReadXmlSchema (xr);
\r
842 public void ReadXmlSchema (XmlReader reader)
\r
845 XmlSchemaDataImporter xsdImporter = new XmlSchemaDataImporter (this, reader, true);
\r
846 xsdImporter.Process ();
\r
848 tableAdapterSchemaInfo = xsdImporter.CurrentAdapter;
\r
851 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
\r
852 SchemaMapper.Read (reader);
\r
856 public XmlReadMode ReadXml (Stream stream)
\r
858 return ReadXml (new XmlTextReader (stream));
\r
861 public XmlReadMode ReadXml (string fileName)
\r
863 XmlTextReader reader = new XmlTextReader (fileName);
\r
865 return ReadXml (reader);
\r
871 public XmlReadMode ReadXml (TextReader reader)
\r
873 return ReadXml (new XmlTextReader (reader));
\r
876 public XmlReadMode ReadXml (XmlReader reader)
\r
878 return ReadXml (reader, XmlReadMode.Auto);
\r
881 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
\r
883 return ReadXml (new XmlTextReader (stream), mode);
\r
886 public XmlReadMode ReadXml (string fileName, XmlReadMode mode)
\r
888 XmlTextReader reader = new XmlTextReader (fileName);
\r
890 return ReadXml (reader, mode);
\r
896 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
\r
898 return ReadXml (new XmlTextReader (reader), mode);
\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
905 if (reader == null)
\r
908 switch (reader.ReadState) {
\r
909 case ReadState.EndOfFile:
\r
910 case ReadState.Error:
\r
911 case ReadState.Closed:
\r
914 // Skip XML declaration and prolog
\r
915 reader.MoveToContent ();
\r
919 if (reader is XmlTextReader) {
\r
920 // we dont need whitespace
\r
921 ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.None;
\r
924 XmlDiffLoader DiffLoader = null;
\r
926 // If diffgram, then read the first element as diffgram
\r
927 if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
\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
938 // (and continue to read)
\r
942 // (and leave rest of the reader as is)
\r
947 // If schema, then read the first element as schema
\r
948 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
950 case XmlReadMode.IgnoreSchema:
\r
951 case XmlReadMode.InferSchema:
\r
953 // (and break up read)
\r
955 case XmlReadMode.Fragment:
\r
956 ReadXmlSchema (reader);
\r
957 // (and continue to read)
\r
959 case XmlReadMode.Auto:
\r
960 if (Tables.Count == 0) {
\r
961 ReadXmlSchema (reader);
\r
962 return XmlReadMode.ReadSchema;
\r
964 // otherwise just ignore and return IgnoreSchema
\r
966 return XmlReadMode.IgnoreSchema;
\r
969 ReadXmlSchema (reader);
\r
970 // (and leave rest of the reader as is)
\r
971 return mode; // When DiffGram, return DiffGram
\r
978 int depth = (reader.NodeType == XmlNodeType.Element) ? reader.Depth : -1;
\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
988 XmlAttribute attr = root.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
\r
989 attr.Prefix = reader.Prefix;
\r
990 attr.Value = reader.GetAttribute(i);
\r
996 XmlReadMode retMode = mode;
\r
997 bool schemaLoaded = false;
\r
1000 if( reader.Depth == depth ||
\r
1001 reader.NodeType == XmlNodeType.EndElement)
\r
1004 if (reader.NodeType != XmlNodeType.Element) {
\r
1005 if (!reader.Read())
\r
1010 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
1012 case XmlReadMode.IgnoreSchema:
\r
1013 case XmlReadMode.InferSchema:
\r
1018 ReadXmlSchema (reader);
\r
1019 retMode = XmlReadMode.ReadSchema;
\r
1020 schemaLoaded = true;
\r
1021 // (and leave rest of the reader as is)
\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
1044 XmlNode n = doc.ReadNode(reader);
\r
1045 root.AppendChild(n);
\r
1048 if (reader.NodeType == XmlNodeType.EndElement)
\r
1050 reader.MoveToContent();
\r
1052 if (mode == XmlReadMode.DiffGram) {
\r
1056 doc.AppendChild(root);
\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
1068 reader = new XmlNodeReader (doc);
\r
1069 XmlDataReader.ReadXml (this, reader, mode);
\r
1071 return retMode == XmlReadMode.Auto ?
\r
1072 XmlReadMode.IgnoreSchema : retMode;
\r
1074 #endregion // Public Methods
\r
1076 #region Public Events
\r
1078 [DataCategory ("Action")]
\r
1080 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
\r
1082 public event MergeFailedEventHandler MergeFailed;
\r
1084 #endregion // Public Events
\r
1086 #region IListSource methods
\r
1087 IList IListSource.GetList ()
\r
1089 return DefaultViewManager;
\r
1092 bool IListSource.ContainsListCollection {
\r
1097 #endregion IListSource methods
\r
1099 #region ISupportInitialize methods
\r
1101 internal bool InitInProgress {
\r
1102 get { return initInProgress; }
\r
1103 set { initInProgress = value; }
\r
1106 public void BeginInit ()
\r
1108 InitInProgress = true;
\r
1110 dataSetInitialized = false;
\r
1114 public void EndInit ()
\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
1122 Tables [i].FinishInit ();
\r
1125 Relations.PostAddRange ();
\r
1126 InitInProgress = false;
\r
1128 dataSetInitialized = true;
\r
1129 DataSetInitialized ();
\r
1134 #region ISerializable
\r
1142 GetObjectData (SerializationInfo info, StreamingContext context)
\r
1145 if (RemotingFormat == SerializationFormat.Xml) {
\r
1146 info.AddValue ("SchemaSerializationMode.DataSet", this.SchemaSerializationMode);
\r
1148 StringWriter sw = new StringWriter ();
\r
1149 XmlTextWriter writer = new XmlTextWriter (sw);
\r
1150 DoWriteXmlSchema (writer);
\r
1152 info.AddValue ("XmlSchema", sw.ToString ());
\r
1154 sw = new StringWriter ();
\r
1155 writer = new XmlTextWriter (sw);
\r
1156 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1158 info.AddValue ("XmlDiffGram", sw.ToString ());
\r
1160 } else /*if (DataSet.RemotingFormat == SerializationFormat.Binary)*/ {
\r
1161 BinarySerialize (info);
\r
1167 #region Protected Methods
\r
1168 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
\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
1177 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
\r
1182 protected virtual void ReadXmlSerializable (XmlReader reader)
\r
1184 ReadXml (reader, XmlReadMode.DiffGram);
\r
1187 void IXmlSerializable.ReadXml (XmlReader reader)
\r
1189 ReadXmlSerializable(reader);
\r
1192 void IXmlSerializable.WriteXml (XmlWriter writer)
\r
1194 DoWriteXmlSchema (writer);
\r
1195 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1198 XmlSchema IXmlSerializable.GetSchema ()
\r
1200 if (GetType() == typeof(DataSet))
\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
1209 protected virtual bool ShouldSerializeRelations ()
\r
1214 protected virtual bool ShouldSerializeTables ()
\r
1220 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
\r
1222 throw new NotImplementedException ();
\r
1226 protected virtual void OnRemoveRelation (DataRelation relation)
\r
1228 throw new NotImplementedException ();
\r
1232 protected virtual void OnRemoveTable (DataTable table)
\r
1234 throw new NotImplementedException ();
\r
1237 internal virtual void OnMergeFailed (MergeFailedEventArgs e)
\r
1239 if (MergeFailed != null)
\r
1240 MergeFailed (this, e);
\r
1242 throw new DataException (e.Conflict);
\r
1246 protected internal void RaisePropertyChanging (string name)
\r
1252 #region Private Methods
\r
1254 internal static string WriteObjectXml (object o)
\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
1265 return XmlConvert.ToString ((DateTime) o, XmlDateTimeSerializationMode.Unspecified);
\r
1267 return XmlConvert.ToString ((DateTime) o);
\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
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
1294 return o.ToString ();
\r
1297 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
\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
1305 internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
\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
1312 internal static void WriteTable (XmlWriter writer,
\r
1314 XmlWriteMode mode,
\r
1315 DataRowVersion version, bool skipIfNested)
\r
1317 if (rows.Length == 0) return;
\r
1318 DataTable table = rows[0].Table;
\r
1320 if (table.TableName == null || table.TableName == "")
\r
1321 throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");
\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
1329 SplitColumns (table, out atts, out elements, out simple);
\r
1330 //sort out the namespacing
\r
1331 int relationCount = table.ParentRelations.Count;
\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
1341 if (row.GetParentRow (prel) != null) {
\r
1350 if (!row.HasVersion(version) ||
\r
1351 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
\r
1352 && version == DataRowVersion.Original))
\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
1364 // If all of the columns were null, we have to write empty element
\r
1366 writer.WriteElementString (XmlHelper.Encode (table.TableName), "");
\r
1370 WriteTableElement (writer, mode, table, row, version);
\r
1372 foreach (DataColumn col in atts)
\r
1373 WriteColumnAsAttribute (writer, mode, col, row, version);
\r
1375 if (simple != null) {
\r
1376 writer.WriteString (WriteObjectXml (row[simple, version]));
\r
1378 foreach (DataColumn col in elements)
\r
1379 WriteColumnAsElement (writer, mode, col, row, version);
\r
1382 foreach (DataRelation relation in table.ChildRelations) {
\r
1383 if (relation.Nested)
\r
1384 WriteTable (writer, row.GetChildRows (relation), mode, version, false);
\r
1387 writer.WriteEndElement ();
\r
1392 internal static void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
\r
1394 string colnspc = null;
\r
1395 object rowObject = row [col, version];
\r
1397 if (rowObject == null || rowObject == DBNull.Value)
\r
1400 if (col.Namespace != String.Empty)
\r
1401 colnspc = col.Namespace;
\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
1408 writer.WriteString (WriteObjectXml (rowObject));
\r
1411 writer.WriteEndElement ();
\r
1414 internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
\r
1416 if (!row.IsNull (col))
\r
1417 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));
\r
1420 internal static void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
\r
1422 //sort out the namespacing
\r
1423 string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;
\r
1425 WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));
\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
1436 if (version != DataRowVersion.Original && modeName != null)
\r
1437 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
\r
1441 internal static void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
\r
1443 writer.WriteStartElement (prefix, name, nspc);
\r
1446 internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
\r
1449 // case XmlWriteMode.WriteSchema:
\r
1450 // writer.WriteAttributeString (prefix, name, nspc);
\r
1452 case XmlWriteMode.DiffGram:
\r
1453 writer.WriteAttributeString (prefix, name, nspc,stringValue);
\r
1456 writer.WriteAttributeString (name, stringValue);
\r
1461 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
\r
1463 if (mode == XmlWriteMode.DiffGram) {
\r
1464 table.SetRowsID ();
\r
1465 WriteDiffGramElement (writer);
\r
1468 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
1470 WriteTable (writer, table, mode, DataRowVersion.Default);
\r
1472 if (mode == XmlWriteMode.DiffGram) {
\r
1473 writer.WriteEndElement (); //DataSet name
\r
1474 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
\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
1482 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
\r
1485 private void DoWriteXmlSchema (XmlWriter writer)
\r
1487 if (writer.WriteState == WriteState.Start)
\r
1488 writer.WriteStartDocument ();
\r
1489 XmlSchemaWriter.WriteXmlSchema (this, writer);
\r
1493 /// Helper function to split columns into attributes elements and simple
\r
1496 internal static void SplitColumns (DataTable table,
\r
1497 out ArrayList atts,
\r
1498 out ArrayList elements,
\r
1499 out DataColumn simple)
\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
1507 //Sort out the columns
\r
1508 foreach (DataColumn col in table.Columns) {
\r
1509 switch (col.ColumnMapping) {
\r
1510 case MappingType.Attribute:
\r
1513 case MappingType.Element:
\r
1514 elements.Add (col);
\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
1523 //ignore Hidden elements
\r
1529 internal static void WriteDiffGramElement (XmlWriter writer)
\r
1531 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
\r
1532 WriteAttributeString (writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
\r
1535 private void SetRowsID ()
\r
1537 foreach (DataTable table in Tables)
\r
1538 table.SetRowsID ();
\r
1541 #endregion //Private Xml Serialisation
\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
1551 protected DataSet (SerializationInfo info, StreamingContext context, bool constructSchema)
\r
1554 if (DetermineSchemaSerializationMode (info, context) == SchemaSerializationMode.ExcludeSchema) {
\r
1555 InitializeDerivedDataSet ();
\r
1558 if (IsBinarySerialized (info, context)) {
\r
1559 BinaryDeserialize (info);
\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
1569 GetSerializationData (info, context);
\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
1580 [Browsable (false)]
\r
1581 public bool IsInitialized {
\r
1582 get { return dataSetInitialized; }
\r
1585 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
1586 [Browsable (false)]
\r
1587 public virtual SchemaSerializationMode SchemaSerializationMode {
\r
1588 get { return SchemaSerializationMode.IncludeSchema; }
\r
1590 if (value != SchemaSerializationMode.IncludeSchema)
\r
1591 throw new InvalidOperationException (
\r
1592 "Only IncludeSchema Mode can be set for Untyped DataSet");
\r
1596 public DataTableReader CreateDataReader (params DataTable[] dataTables)
\r
1598 return new DataTableReader (dataTables);
\r
1601 public DataTableReader CreateDataReader ()
\r
1603 return new DataTableReader ((DataTable[])Tables.ToArray (typeof (DataTable)));
\r
1606 public static XmlSchemaComplexType GetDataSetSchema (XmlSchemaSet schemaSet)
\r
1608 return new XmlSchemaComplexType ();
\r
1611 public void Load (IDataReader reader, LoadOption loadOption, params DataTable[] tables)
\r
1613 if (reader == null)
\r
1614 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\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
1624 public void Load (IDataReader reader, LoadOption loadOption, params string[] tables)
\r
1626 if (reader == null)
\r
1627 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1629 foreach (string tableName in tables) {
\r
1630 DataTable dt = Tables [tableName];
\r
1633 dt = new DataTable (tableName);
\r
1636 dt.Load (reader, loadOption);
\r
1637 reader.NextResult ();
\r
1641 public virtual void Load (IDataReader reader, LoadOption loadOption,
\r
1642 FillErrorEventHandler errorHandler, params DataTable[] tables)
\r
1644 if (reader == null)
\r
1645 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\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
1655 void BinarySerialize (SerializationInfo si)
\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
1668 Tables.BinarySerialize_Schema (si);
\r
1669 Tables.BinarySerialize_Data (si);
\r
1671 Relations.BinarySerialize (si);
\r
1674 void BinaryDeserialize (SerializationInfo info)
\r
1676 ArrayList arrayList = null;
\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
1685 FIXME: Private variable available in SerializationInfo
\r
1686 this.RemotingVersion = (System.Version) info.GetValue("DataSet.RemotingVersion",
\r
1687 typeof(System.Version));
\r
1689 properties = (PropertyCollection) info.GetValue ("DataSet.ExtendedProperties",
\r
1690 typeof (PropertyCollection));
\r
1691 int tableCount = info.GetInt32 ("DataSet.Tables.Count");
\r
1694 DataTable dt = null;
\r
1695 for (int i = 0; i < tableCount; i++) {
\r
1696 bytes = (Byte []) info.GetValue ("DataSet.Tables_" + i,
\r
1698 MemoryStream ms = new MemoryStream (bytes);
\r
1699 BinaryFormatter bf = new BinaryFormatter ();
\r
1700 dt = (DataTable) bf.Deserialize (ms);
\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
1709 int rowsCount = info.GetInt32 ("DataTable_" + i + ".Rows.Count");
\r
1710 int recordsCount = info.GetInt32 ("DataTable_" + i + ".Records.Count");
\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
1721 for (int i = 0; i < tableCount; 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
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
1746 childColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].
\r
1747 Columns [(int) dataColumnArray.GetValue (1)]);
\r
1748 bParentColumn = true;
\r
1752 Relations.Add ((string) tmpArrayList [0],
\r
1753 (DataColumn []) parentColumns.ToArray (typeof (DataColumn)),
\r
1754 (DataColumn []) childColumns.ToArray (typeof (DataColumn)),
\r
1759 private void OnDataSetInitialized (EventArgs e)
\r
1761 if (null != Initialized)
\r
1762 Initialized (this, e);
\r
1765 private void DataSetInitialized ()
\r
1767 EventArgs e = new EventArgs ();
\r
1768 OnDataSetInitialized (e);
\r
1771 protected virtual void InitializeDerivedDataSet ()
\r
1775 protected SchemaSerializationMode DetermineSchemaSerializationMode (XmlReader reader)
\r
1777 return SchemaSerializationMode.IncludeSchema;
\r
1780 protected SchemaSerializationMode DetermineSchemaSerializationMode (SerializationInfo info, StreamingContext context)
\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
1789 return SchemaSerializationMode.IncludeSchema;
\r
1792 protected bool IsBinarySerialized (SerializationInfo info, StreamingContext context)
\r
1794 SerializationInfoEnumerator e = info.GetEnumerator ();
\r
1795 while (e.MoveNext ()) {
\r
1796 if (e.ObjectType == typeof (System.Data.SerializationFormat))
\r