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 // Don't check for ReadOnly, when cloning data to new uninitialized row.
\r
572 row.CopyValuesToRow (newRow, false);
\r
573 newRow.XmlRowID = row.XmlRowID;
\r
574 addedRows.Add (row, row);
\r
577 public string GetXml ()
\r
579 StringWriter Writer = new StringWriter ();
\r
580 WriteXml (Writer, XmlWriteMode.IgnoreSchema);
\r
581 return Writer.ToString ();
\r
584 public string GetXmlSchema ()
\r
586 StringWriter Writer = new StringWriter ();
\r
587 WriteXmlSchema (Writer);
\r
588 return Writer.ToString ();
\r
591 public bool HasChanges ()
\r
593 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
\r
596 public bool HasChanges (DataRowState rowStates)
\r
598 if (((int) rowStates & 0xffffffe0) != 0)
\r
599 throw new ArgumentOutOfRangeException ("rowStates");
\r
601 DataTableCollection tableCollection = Tables;
\r
603 DataRowCollection rowCollection;
\r
606 for (int i = 0; i < tableCollection.Count; i++) {
\r
607 table = tableCollection [i];
\r
608 rowCollection = table.Rows;
\r
609 for (int j = 0; j < rowCollection.Count; j++) {
\r
610 row = rowCollection [j];
\r
611 if ((row.RowState & rowStates) != 0)
\r
619 public void InferXmlSchema (XmlReader reader, string[] nsArray)
\r
621 if (reader == null)
\r
623 XmlDocument doc = new XmlDocument ();
\r
625 InferXmlSchema (doc, nsArray);
\r
628 private void InferXmlSchema (XmlDocument doc, string [] nsArray)
\r
630 XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
\r
633 public void InferXmlSchema (Stream stream, string[] nsArray)
\r
635 InferXmlSchema (new XmlTextReader (stream), nsArray);
\r
638 public void InferXmlSchema (TextReader reader, string[] nsArray)
\r
640 InferXmlSchema (new XmlTextReader (reader), nsArray);
\r
643 public void InferXmlSchema (string fileName, string[] nsArray)
\r
645 XmlTextReader reader = new XmlTextReader (fileName);
\r
647 InferXmlSchema (reader, nsArray);
\r
653 public virtual void RejectChanges ()
\r
656 bool oldEnforceConstraints = this.EnforceConstraints;
\r
657 this.EnforceConstraints = false;
\r
659 for (i = 0; i < this.Tables.Count;i++)
\r
660 this.Tables[i].RejectChanges ();
\r
662 this.EnforceConstraints = oldEnforceConstraints;
\r
665 public virtual void Reset ()
\r
667 // first we remove all ForeignKeyConstraints (if we will not do that
\r
668 // we will get an exception when clearing the tables).
\r
669 for (int i = 0; i < Tables.Count; i++) {
\r
670 ConstraintCollection cc = Tables[i].Constraints;
\r
671 for (int j = 0; j < cc.Count; j++) {
\r
672 if (cc[j] is ForeignKeyConstraint)
\r
678 Relations.Clear ();
\r
682 public void WriteXml (Stream stream)
\r
684 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
685 writer.Formatting = Formatting.Indented;
\r
690 /// Writes the current data for the DataSet to the specified file.
\r
692 /// <param name="filename">Fully qualified filename to write to</param>
\r
693 public void WriteXml (string fileName)
\r
695 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
696 writer.Formatting = Formatting.Indented;
\r
697 writer.WriteStartDocument (true);
\r
701 writer.WriteEndDocument ();
\r
706 public void WriteXml (TextWriter writer)
\r
708 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
709 xwriter.Formatting = Formatting.Indented;
\r
710 WriteXml (xwriter);
\r
713 public void WriteXml (XmlWriter writer)
\r
715 WriteXml (writer, XmlWriteMode.IgnoreSchema);
\r
718 public void WriteXml (string fileName, XmlWriteMode mode)
\r
720 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
721 writer.Formatting = Formatting.Indented;
\r
722 writer.WriteStartDocument (true);
\r
725 WriteXml (writer, mode);
\r
727 writer.WriteEndDocument ();
\r
732 public void WriteXml (Stream stream, XmlWriteMode mode)
\r
734 XmlTextWriter writer = new XmlTextWriter (stream, null);
\r
735 writer.Formatting = Formatting.Indented;
\r
736 WriteXml (writer, mode);
\r
739 public void WriteXml (TextWriter writer, XmlWriteMode mode)
\r
741 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
742 xwriter.Formatting = Formatting.Indented;
\r
743 WriteXml (xwriter, mode);
\r
746 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
\r
748 if (mode == XmlWriteMode.DiffGram) {
\r
750 WriteDiffGramElement(writer);
\r
753 // It should not write when there is no content to be written
\r
754 bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
\r
755 for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)
\r
756 shouldOutputContent = tableCollection [n].Rows.Count > 0;
\r
758 if (shouldOutputContent) {
\r
759 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
761 if (mode == XmlWriteMode.WriteSchema)
\r
762 DoWriteXmlSchema (writer);
\r
764 WriteTables (writer, mode, Tables, DataRowVersion.Default);
\r
765 writer.WriteEndElement ();
\r
768 if (mode == XmlWriteMode.DiffGram) {
\r
769 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
\r
770 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
\r
771 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
\r
772 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
\r
773 writer.WriteEndElement ();
\r
777 if (mode == XmlWriteMode.DiffGram)
\r
778 writer.WriteEndElement (); // diffgr:diffgram
\r
783 public void WriteXmlSchema (Stream stream)
\r
785 XmlTextWriter writer = new XmlTextWriter (stream, null );
\r
786 writer.Formatting = Formatting.Indented;
\r
787 WriteXmlSchema (writer);
\r
790 public void WriteXmlSchema (string fileName)
\r
792 XmlTextWriter writer = new XmlTextWriter (fileName, null);
\r
794 writer.Formatting = Formatting.Indented;
\r
795 writer.WriteStartDocument (true);
\r
796 WriteXmlSchema (writer);
\r
798 writer.WriteEndDocument ();
\r
803 public void WriteXmlSchema (TextWriter writer)
\r
805 XmlTextWriter xwriter = new XmlTextWriter (writer);
\r
807 xwriter.Formatting = Formatting.Indented;
\r
808 WriteXmlSchema (xwriter);
\r
814 public void WriteXmlSchema (XmlWriter writer)
\r
816 //Create a skeleton doc and then write the schema
\r
817 //proper which is common to the WriteXml method in schema mode
\r
818 DoWriteXmlSchema (writer);
\r
821 public void ReadXmlSchema (Stream stream)
\r
823 XmlReader reader = new XmlTextReader (stream, null);
\r
824 ReadXmlSchema (reader);
\r
827 public void ReadXmlSchema (string fileName)
\r
829 XmlReader reader = new XmlTextReader (fileName);
\r
831 ReadXmlSchema (reader);
\r
837 public void ReadXmlSchema (TextReader reader)
\r
839 XmlReader xr = new XmlTextReader (reader);
\r
840 ReadXmlSchema (xr);
\r
843 public void ReadXmlSchema (XmlReader reader)
\r
846 XmlSchemaDataImporter xsdImporter = new XmlSchemaDataImporter (this, reader, true);
\r
847 xsdImporter.Process ();
\r
849 tableAdapterSchemaInfo = xsdImporter.CurrentAdapter;
\r
852 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
\r
853 SchemaMapper.Read (reader);
\r
857 public XmlReadMode ReadXml (Stream stream)
\r
859 return ReadXml (new XmlTextReader (stream));
\r
862 public XmlReadMode ReadXml (string fileName)
\r
864 XmlTextReader reader = new XmlTextReader (fileName);
\r
866 return ReadXml (reader);
\r
872 public XmlReadMode ReadXml (TextReader reader)
\r
874 return ReadXml (new XmlTextReader (reader));
\r
877 public XmlReadMode ReadXml (XmlReader reader)
\r
879 return ReadXml (reader, XmlReadMode.Auto);
\r
882 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
\r
884 return ReadXml (new XmlTextReader (stream), mode);
\r
887 public XmlReadMode ReadXml (string fileName, XmlReadMode mode)
\r
889 XmlTextReader reader = new XmlTextReader (fileName);
\r
891 return ReadXml (reader, mode);
\r
897 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
\r
899 return ReadXml (new XmlTextReader (reader), mode);
\r
902 // LAMESPEC: XmlReadMode.Fragment is far from presisely
\r
903 // documented. MS.NET infers schema against this mode.
\r
904 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
\r
906 if (reader == null)
\r
909 switch (reader.ReadState) {
\r
910 case ReadState.EndOfFile:
\r
911 case ReadState.Error:
\r
912 case ReadState.Closed:
\r
915 // Skip XML declaration and prolog
\r
916 reader.MoveToContent ();
\r
920 if (reader is XmlTextReader) {
\r
921 // we dont need whitespace
\r
922 ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.None;
\r
925 XmlDiffLoader DiffLoader = null;
\r
927 // If diffgram, then read the first element as diffgram
\r
928 if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
\r
930 case XmlReadMode.Auto:
\r
931 case XmlReadMode.DiffGram:
\r
932 if (DiffLoader == null)
\r
933 DiffLoader = new XmlDiffLoader (this);
\r
934 DiffLoader.Load (reader);
\r
935 // (and leave rest of the reader as is)
\r
936 return XmlReadMode.DiffGram;
\r
937 case XmlReadMode.Fragment:
\r
939 // (and continue to read)
\r
943 // (and leave rest of the reader as is)
\r
948 // If schema, then read the first element as schema
\r
949 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
951 case XmlReadMode.IgnoreSchema:
\r
952 case XmlReadMode.InferSchema:
\r
954 // (and break up read)
\r
956 case XmlReadMode.Fragment:
\r
957 ReadXmlSchema (reader);
\r
958 // (and continue to read)
\r
960 case XmlReadMode.Auto:
\r
961 if (Tables.Count == 0) {
\r
962 ReadXmlSchema (reader);
\r
963 return XmlReadMode.ReadSchema;
\r
965 // otherwise just ignore and return IgnoreSchema
\r
967 return XmlReadMode.IgnoreSchema;
\r
970 ReadXmlSchema (reader);
\r
971 // (and leave rest of the reader as is)
\r
972 return mode; // When DiffGram, return DiffGram
\r
979 int depth = (reader.NodeType == XmlNodeType.Element) ? reader.Depth : -1;
\r
981 XmlDocument doc = new XmlDocument ();
\r
982 XmlElement root = doc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
\r
983 if (reader.HasAttributes) {
\r
984 for (int i = 0; i < reader.AttributeCount; i++) {
\r
985 reader.MoveToAttribute(i);
\r
986 if (reader.NamespaceURI == XmlConstants.XmlnsNS)
\r
987 root.SetAttribute(reader.Name, reader.GetAttribute(i));
\r
989 XmlAttribute attr = root.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
\r
990 attr.Prefix = reader.Prefix;
\r
991 attr.Value = reader.GetAttribute(i);
\r
997 XmlReadMode retMode = mode;
\r
998 bool schemaLoaded = false;
\r
1001 if( reader.Depth == depth ||
\r
1002 reader.NodeType == XmlNodeType.EndElement)
\r
1005 if (reader.NodeType != XmlNodeType.Element) {
\r
1006 if (!reader.Read())
\r
1011 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
\r
1013 case XmlReadMode.IgnoreSchema:
\r
1014 case XmlReadMode.InferSchema:
\r
1019 ReadXmlSchema (reader);
\r
1020 retMode = XmlReadMode.ReadSchema;
\r
1021 schemaLoaded = true;
\r
1022 // (and leave rest of the reader as is)
\r
1029 if ((reader.LocalName == "diffgram") && (reader.NamespaceURI == XmlConstants.DiffgrNamespace)) {
\r
1030 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)
\r
1031 || mode == XmlReadMode.Auto) {
\r
1032 if (DiffLoader == null)
\r
1033 DiffLoader = new XmlDiffLoader (this);
\r
1034 DiffLoader.Load (reader);
\r
1035 // (and leave rest of the reader as is)
\r
1036 retMode = XmlReadMode.DiffGram;
\r
1045 XmlNode n = doc.ReadNode(reader);
\r
1046 root.AppendChild(n);
\r
1049 if (reader.NodeType == XmlNodeType.EndElement)
\r
1051 reader.MoveToContent();
\r
1053 if (mode == XmlReadMode.DiffGram) {
\r
1057 doc.AppendChild(root);
\r
1059 if (!schemaLoaded &&
\r
1060 retMode != XmlReadMode.ReadSchema &&
\r
1061 mode != XmlReadMode.IgnoreSchema &&
\r
1062 mode != XmlReadMode.Fragment &&
\r
1063 (Tables.Count == 0 || mode == XmlReadMode.InferSchema)) {
\r
1064 InferXmlSchema(doc, null);
\r
1065 if (mode == XmlReadMode.Auto)
\r
1066 retMode = XmlReadMode.InferSchema;
\r
1069 reader = new XmlNodeReader (doc);
\r
1070 XmlDataReader.ReadXml (this, reader, mode);
\r
1072 return retMode == XmlReadMode.Auto ?
\r
1073 XmlReadMode.IgnoreSchema : retMode;
\r
1075 #endregion // Public Methods
\r
1077 #region Public Events
\r
1079 [DataCategory ("Action")]
\r
1081 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
\r
1083 public event MergeFailedEventHandler MergeFailed;
\r
1085 #endregion // Public Events
\r
1087 #region IListSource methods
\r
1088 IList IListSource.GetList ()
\r
1090 return DefaultViewManager;
\r
1093 bool IListSource.ContainsListCollection {
\r
1098 #endregion IListSource methods
\r
1100 #region ISupportInitialize methods
\r
1102 internal bool InitInProgress {
\r
1103 get { return initInProgress; }
\r
1104 set { initInProgress = value; }
\r
1107 public void BeginInit ()
\r
1109 InitInProgress = true;
\r
1111 dataSetInitialized = false;
\r
1115 public void EndInit ()
\r
1117 // Finsh the init'ing the tables only after adding all the
\r
1118 // tables to the collection.
\r
1119 Tables.PostAddRange ();
\r
1120 for (int i=0; i < Tables.Count; ++i) {
\r
1121 if (!Tables [i].InitInProgress)
\r
1123 Tables [i].FinishInit ();
\r
1126 Relations.PostAddRange ();
\r
1127 InitInProgress = false;
\r
1129 dataSetInitialized = true;
\r
1130 DataSetInitialized ();
\r
1135 #region ISerializable
\r
1143 GetObjectData (SerializationInfo info, StreamingContext context)
\r
1146 if (RemotingFormat == SerializationFormat.Xml) {
\r
1147 info.AddValue ("SchemaSerializationMode.DataSet", this.SchemaSerializationMode);
\r
1149 StringWriter sw = new StringWriter ();
\r
1150 XmlTextWriter writer = new XmlTextWriter (sw);
\r
1151 DoWriteXmlSchema (writer);
\r
1153 info.AddValue ("XmlSchema", sw.ToString ());
\r
1155 sw = new StringWriter ();
\r
1156 writer = new XmlTextWriter (sw);
\r
1157 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1159 info.AddValue ("XmlDiffGram", sw.ToString ());
\r
1161 } else /*if (DataSet.RemotingFormat == SerializationFormat.Binary)*/ {
\r
1162 BinarySerialize (info);
\r
1168 #region Protected Methods
\r
1169 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
\r
1171 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
\r
1172 XmlTextReader reader = new XmlTextReader (new StringReader (s));
\r
1173 ReadXml (reader, XmlReadMode.DiffGram);
\r
1178 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
\r
1183 protected virtual void ReadXmlSerializable (XmlReader reader)
\r
1185 ReadXml (reader, XmlReadMode.DiffGram);
\r
1188 void IXmlSerializable.ReadXml (XmlReader reader)
\r
1190 ReadXmlSerializable(reader);
\r
1193 void IXmlSerializable.WriteXml (XmlWriter writer)
\r
1195 DoWriteXmlSchema (writer);
\r
1196 WriteXml (writer, XmlWriteMode.DiffGram);
\r
1199 XmlSchema IXmlSerializable.GetSchema ()
\r
1201 if (GetType() == typeof(DataSet))
\r
1203 MemoryStream stream = new MemoryStream();
\r
1204 XmlTextWriter writer = new XmlTextWriter(stream, null);
\r
1205 WriteXmlSchema(writer);
\r
1206 stream.Position = 0;
\r
1207 return XmlSchema.Read(new XmlTextReader(stream), (ValidationEventHandler)null);
\r
1210 protected virtual bool ShouldSerializeRelations ()
\r
1215 protected virtual bool ShouldSerializeTables ()
\r
1221 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
\r
1223 throw new NotImplementedException ();
\r
1227 protected virtual void OnRemoveRelation (DataRelation relation)
\r
1229 throw new NotImplementedException ();
\r
1233 protected virtual void OnRemoveTable (DataTable table)
\r
1235 throw new NotImplementedException ();
\r
1238 internal virtual void OnMergeFailed (MergeFailedEventArgs e)
\r
1240 if (MergeFailed != null)
\r
1241 MergeFailed (this, e);
\r
1243 throw new DataException (e.Conflict);
\r
1247 protected internal void RaisePropertyChanging (string name)
\r
1253 #region Private Methods
\r
1255 internal static string WriteObjectXml (object o)
\r
1257 switch (Type.GetTypeCode (o.GetType ())) {
\r
1258 case TypeCode.Boolean:
\r
1259 return XmlConvert.ToString ((Boolean) o);
\r
1260 case TypeCode.Byte:
\r
1261 return XmlConvert.ToString ((Byte) o);
\r
1262 case TypeCode.Char:
\r
1263 return XmlConvert.ToString ((Char) o);
\r
1264 case TypeCode.DateTime:
\r
1266 return XmlConvert.ToString ((DateTime) o, XmlDateTimeSerializationMode.Unspecified);
\r
1268 return XmlConvert.ToString ((DateTime) o);
\r
1270 case TypeCode.Decimal:
\r
1271 return XmlConvert.ToString ((Decimal) o);
\r
1272 case TypeCode.Double:
\r
1273 return XmlConvert.ToString ((Double) o);
\r
1274 case TypeCode.Int16:
\r
1275 return XmlConvert.ToString ((Int16) o);
\r
1276 case TypeCode.Int32:
\r
1277 return XmlConvert.ToString ((Int32) o);
\r
1278 case TypeCode.Int64:
\r
1279 return XmlConvert.ToString ((Int64) o);
\r
1280 case TypeCode.SByte:
\r
1281 return XmlConvert.ToString ((SByte) o);
\r
1282 case TypeCode.Single:
\r
1283 return XmlConvert.ToString ((Single) o);
\r
1284 case TypeCode.UInt16:
\r
1285 return XmlConvert.ToString ((UInt16) o);
\r
1286 case TypeCode.UInt32:
\r
1287 return XmlConvert.ToString ((UInt32) o);
\r
1288 case TypeCode.UInt64:
\r
1289 return XmlConvert.ToString ((UInt64) o);
\r
1291 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
\r
1292 if (o is Guid) return XmlConvert.ToString ((Guid) o);
\r
1293 if (o is byte[]) return Convert.ToBase64String ((byte[])o);
\r
1295 return o.ToString ();
\r
1298 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
\r
1300 //WriteTable takes care of skipping a table if it has a
\r
1301 //Nested Parent Relationship
\r
1302 foreach (DataTable table in tableCollection)
\r
1303 WriteTable ( writer, table, mode, version);
\r
1306 internal static void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
\r
1308 DataRow[] rows = table.NewRowArray(table.Rows.Count);
\r
1309 table.Rows.CopyTo (rows, 0);
\r
1310 WriteTable (writer, rows, mode, version, true);
\r
1313 internal static void WriteTable (XmlWriter writer,
\r
1315 XmlWriteMode mode,
\r
1316 DataRowVersion version, bool skipIfNested)
\r
1318 if (rows.Length == 0) return;
\r
1319 DataTable table = rows[0].Table;
\r
1321 if (table.TableName == null || table.TableName == "")
\r
1322 throw new InvalidOperationException("Cannot serialize the DataTable. DataTable name is not set.");
\r
1324 //The columns can be attributes, hidden, elements, or simple content
\r
1325 //There can be 0-1 simple content cols or 0-* elements
\r
1326 System.Collections.ArrayList atts;
\r
1327 System.Collections.ArrayList elements;
\r
1328 DataColumn simple = null;
\r
1330 SplitColumns (table, out atts, out elements, out simple);
\r
1331 //sort out the namespacing
\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 || col.DataType == typeof (object)) {
\r
1407 IXmlSerializable serializableObj = rowObject as IXmlSerializable;
\r
1408 if (serializableObj == null)
\r
1409 throw new InvalidOperationException ();
\r
1410 ((IXmlSerializable)rowObject).WriteXml (writer);
\r
1412 writer.WriteString (WriteObjectXml (rowObject));
\r
1415 writer.WriteEndElement ();
\r
1418 internal static void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
\r
1420 if (!row.IsNull (col))
\r
1421 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlHelper.Encode (col.ColumnName), WriteObjectXml (row[col, version]));
\r
1424 internal static void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
\r
1426 //sort out the namespacing
\r
1427 string nspc = (table.Namespace.Length > 0 || table.DataSet == null) ? table.Namespace : table.DataSet.Namespace;
\r
1429 WriteStartElement (writer, mode, nspc, table.Prefix, XmlHelper.Encode (table.TableName));
\r
1431 if (mode == XmlWriteMode.DiffGram) {
\r
1432 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
\r
1433 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));
\r
1434 string modeName = null;
\r
1435 if (row.RowState == DataRowState.Modified)
\r
1436 modeName = "modified";
\r
1437 else if (row.RowState == DataRowState.Added)
\r
1438 modeName = "inserted";
\r
1440 if (version != DataRowVersion.Original && modeName != null)
\r
1441 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
\r
1445 internal static void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
\r
1447 writer.WriteStartElement (prefix, name, nspc);
\r
1450 internal static void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
\r
1453 // case XmlWriteMode.WriteSchema:
\r
1454 // writer.WriteAttributeString (prefix, name, nspc);
\r
1456 case XmlWriteMode.DiffGram:
\r
1457 writer.WriteAttributeString (prefix, name, nspc,stringValue);
\r
1460 writer.WriteAttributeString (name, stringValue);
\r
1465 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
\r
1467 if (mode == XmlWriteMode.DiffGram) {
\r
1468 table.SetRowsID ();
\r
1469 WriteDiffGramElement (writer);
\r
1472 WriteStartElement (writer, mode, Namespace, Prefix, XmlHelper.Encode (DataSetName));
\r
1474 WriteTable (writer, table, mode, DataRowVersion.Default);
\r
1476 if (mode == XmlWriteMode.DiffGram) {
\r
1477 writer.WriteEndElement (); //DataSet name
\r
1478 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
\r
1480 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
\r
1481 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
\r
1482 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
\r
1483 writer.WriteEndElement ();
\r
1486 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
\r
1489 private void DoWriteXmlSchema (XmlWriter writer)
\r
1491 if (writer.WriteState == WriteState.Start)
\r
1492 writer.WriteStartDocument ();
\r
1493 XmlSchemaWriter.WriteXmlSchema (this, writer);
\r
1497 /// Helper function to split columns into attributes elements and simple
\r
1500 internal static void SplitColumns (DataTable table,
\r
1501 out ArrayList atts,
\r
1502 out ArrayList elements,
\r
1503 out DataColumn simple)
\r
1505 //The columns can be attributes, hidden, elements, or simple content
\r
1506 //There can be 0-1 simple content cols or 0-* elements
\r
1507 atts = new System.Collections.ArrayList ();
\r
1508 elements = new System.Collections.ArrayList ();
\r
1511 //Sort out the columns
\r
1512 foreach (DataColumn col in table.Columns) {
\r
1513 switch (col.ColumnMapping) {
\r
1514 case MappingType.Attribute:
\r
1517 case MappingType.Element:
\r
1518 elements.Add (col);
\r
1520 case MappingType.SimpleContent:
\r
1521 if (simple != null) {
\r
1522 throw new System.InvalidOperationException ("There may only be one simple content element");
\r
1527 //ignore Hidden elements
\r
1533 internal static void WriteDiffGramElement (XmlWriter writer)
\r
1535 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
\r
1536 WriteAttributeString (writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
\r
1539 private void SetRowsID ()
\r
1541 foreach (DataTable table in Tables)
\r
1542 table.SetRowsID ();
\r
1545 #endregion //Private Xml Serialisation
\r
1549 [XmlSchemaProvider ("GetDataSetSchema")]
\r
1550 [XmlRoot ("DataSet")]
\r
1551 partial class DataSet : ISupportInitializeNotification {
\r
1552 private bool dataSetInitialized = true;
\r
1553 public event EventHandler Initialized;
\r
1555 protected DataSet (SerializationInfo info, StreamingContext context, bool constructSchema)
\r
1558 if (DetermineSchemaSerializationMode (info, context) == SchemaSerializationMode.ExcludeSchema) {
\r
1559 InitializeDerivedDataSet ();
\r
1562 if (IsBinarySerialized (info, context)) {
\r
1563 BinaryDeserialize (info);
\r
1567 if (constructSchema) {
\r
1568 string s = info.GetValue ("XmlSchema", typeof (String)) as String;
\r
1569 XmlTextReader reader = new XmlTextReader (new StringReader (s));
\r
1570 ReadXmlSchema (reader);
\r
1573 GetSerializationData (info, context);
\r
1577 SerializationFormat remotingFormat = SerializationFormat.Xml;
\r
1578 [DefaultValue (SerializationFormat.Xml)]
\r
1579 public SerializationFormat RemotingFormat {
\r
1580 get { return remotingFormat; }
\r
1581 set { remotingFormat = value; }
\r
1584 [Browsable (false)]
\r
1585 public bool IsInitialized {
\r
1586 get { return dataSetInitialized; }
\r
1589 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
\r
1590 [Browsable (false)]
\r
1591 public virtual SchemaSerializationMode SchemaSerializationMode {
\r
1592 get { return SchemaSerializationMode.IncludeSchema; }
\r
1594 if (value != SchemaSerializationMode.IncludeSchema)
\r
1595 throw new InvalidOperationException (
\r
1596 "Only IncludeSchema Mode can be set for Untyped DataSet");
\r
1600 public DataTableReader CreateDataReader (params DataTable[] dataTables)
\r
1602 return new DataTableReader (dataTables);
\r
1605 public DataTableReader CreateDataReader ()
\r
1607 return new DataTableReader ((DataTable[])Tables.ToArray (typeof (DataTable)));
\r
1610 public static XmlSchemaComplexType GetDataSetSchema (XmlSchemaSet schemaSet)
\r
1612 return new XmlSchemaComplexType ();
\r
1615 public void Load (IDataReader reader, LoadOption loadOption, params DataTable[] tables)
\r
1617 if (reader == null)
\r
1618 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1620 foreach (DataTable dt in tables) {
\r
1621 if (dt.DataSet == null || dt.DataSet != this)
\r
1622 throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");
\r
1623 dt.Load (reader, loadOption);
\r
1624 reader.NextResult ();
\r
1628 public void Load (IDataReader reader, LoadOption loadOption, params string[] tables)
\r
1630 if (reader == null)
\r
1631 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1633 foreach (string tableName in tables) {
\r
1634 DataTable dt = Tables [tableName];
\r
1637 dt = new DataTable (tableName);
\r
1640 dt.Load (reader, loadOption);
\r
1641 reader.NextResult ();
\r
1645 public virtual void Load (IDataReader reader, LoadOption loadOption,
\r
1646 FillErrorEventHandler errorHandler, params DataTable[] tables)
\r
1648 if (reader == null)
\r
1649 throw new ArgumentNullException ("Value cannot be null. Parameter name: reader");
\r
1651 foreach (DataTable dt in tables) {
\r
1652 if (dt.DataSet == null || dt.DataSet != this)
\r
1653 throw new ArgumentException ("Table " + dt.TableName + " does not belong to this DataSet.");
\r
1654 dt.Load (reader, loadOption, errorHandler);
\r
1655 reader.NextResult ();
\r
1659 void BinarySerialize (SerializationInfo si)
\r
1661 Version vr = new Version(2, 0);
\r
1662 si.AddValue ("DataSet.RemotingVersion", vr, typeof (Version));
\r
1663 si.AddValue ("DataSet.RemotingFormat", RemotingFormat, typeof (SerializationFormat));
\r
1664 si.AddValue ("DataSet.DataSetName", DataSetName);
\r
1665 si.AddValue ("DataSet.Namespace", Namespace);
\r
1666 si.AddValue ("DataSet.Prefix", Prefix);
\r
1667 si.AddValue ("DataSet.CaseSensitive", CaseSensitive);
\r
1668 si.AddValue ("DataSet.LocaleLCID", Locale.LCID);
\r
1669 si.AddValue ("DataSet.EnforceConstraints", EnforceConstraints);
\r
1670 si.AddValue ("DataSet.ExtendedProperties", properties, typeof (PropertyCollection));
\r
1672 Tables.BinarySerialize_Schema (si);
\r
1673 Tables.BinarySerialize_Data (si);
\r
1675 Relations.BinarySerialize (si);
\r
1678 void BinaryDeserialize (SerializationInfo info)
\r
1680 ArrayList arrayList = null;
\r
1682 DataSetName = info.GetString ("DataSet.DataSetName");
\r
1683 Namespace = info.GetString ("DataSet.Namespace");
\r
1684 CaseSensitive = info.GetBoolean ("DataSet.CaseSensitive");
\r
1685 Locale = new CultureInfo (info.GetInt32 ("DataSet.LocaleLCID"));
\r
1686 EnforceConstraints = info.GetBoolean ("DataSet.EnforceConstraints");
\r
1687 Prefix = info.GetString ("DataSet.Prefix");
\r
1689 FIXME: Private variable available in SerializationInfo
\r
1690 this.RemotingVersion = (System.Version) info.GetValue("DataSet.RemotingVersion",
\r
1691 typeof(System.Version));
\r
1693 properties = (PropertyCollection) info.GetValue ("DataSet.ExtendedProperties",
\r
1694 typeof (PropertyCollection));
\r
1695 int tableCount = info.GetInt32 ("DataSet.Tables.Count");
\r
1698 DataTable dt = null;
\r
1699 for (int i = 0; i < tableCount; i++) {
\r
1700 bytes = (Byte []) info.GetValue ("DataSet.Tables_" + i,
\r
1702 MemoryStream ms = new MemoryStream (bytes);
\r
1703 BinaryFormatter bf = new BinaryFormatter ();
\r
1704 dt = (DataTable) bf.Deserialize (ms);
\r
1706 for (int j = 0; j < dt.Columns.Count; j++) {
\r
1707 dt.Columns[j].Expression = info.GetString ("DataTable_" + i +
\r
1708 ".DataColumn_" + j +
\r
1713 int rowsCount = info.GetInt32 ("DataTable_" + i + ".Rows.Count");
\r
1714 int recordsCount = info.GetInt32 ("DataTable_" + i + ".Records.Count");
\r
1716 ArrayList nullBits = (ArrayList) info.GetValue ("DataTable_" + i + ".NullBits",
\r
1717 typeof (ArrayList));
\r
1718 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Records",
\r
1719 typeof (ArrayList));
\r
1720 BitArray rowStateBitArray = (BitArray) info.GetValue ("DataTable_" + i + ".RowStates",
\r
1721 typeof (BitArray));
\r
1722 dt.DeserializeRecords (arrayList, nullBits, rowStateBitArray);
\r
1725 for (int i = 0; i < tableCount; i++) {
\r
1727 dt.dataSet = this;
\r
1728 arrayList = (ArrayList) info.GetValue ("DataTable_" + i + ".Constraints",
\r
1729 typeof (ArrayList));
\r
1730 if (dt.Constraints == null)
\r
1731 dt.Constraints = new ConstraintCollection (dt);
\r
1732 dt.DeserializeConstraints (arrayList);
\r
1734 arrayList = (ArrayList) info.GetValue ("DataSet.Relations",
\r
1735 typeof (ArrayList));
\r
1736 bool bParentColumn = true;
\r
1737 for (int l = 0; l < arrayList.Count; l++) {
\r
1738 ArrayList tmpArrayList = (ArrayList) arrayList[l];
\r
1739 ArrayList childColumns = new ArrayList ();
\r
1740 ArrayList parentColumns = new ArrayList ();
\r
1741 for (int k = 0; k < tmpArrayList.Count; k++) {
\r
1742 if (tmpArrayList[k] != null && typeof (int) == tmpArrayList[k].GetType().GetElementType()) {
\r
1743 Array dataColumnArray = (Array)tmpArrayList[k];
\r
1744 if (bParentColumn) {
\r
1745 parentColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].
\r
1746 Columns [(int) dataColumnArray.GetValue (1)]);
\r
1747 bParentColumn = false;
\r
1750 childColumns.Add (Tables [(int) dataColumnArray.GetValue (0)].
\r
1751 Columns [(int) dataColumnArray.GetValue (1)]);
\r
1752 bParentColumn = true;
\r
1756 Relations.Add ((string) tmpArrayList [0],
\r
1757 (DataColumn []) parentColumns.ToArray (typeof (DataColumn)),
\r
1758 (DataColumn []) childColumns.ToArray (typeof (DataColumn)),
\r
1763 private void OnDataSetInitialized (EventArgs e)
\r
1765 if (null != Initialized)
\r
1766 Initialized (this, e);
\r
1769 private void DataSetInitialized ()
\r
1771 EventArgs e = new EventArgs ();
\r
1772 OnDataSetInitialized (e);
\r
1775 protected virtual void InitializeDerivedDataSet ()
\r
1779 protected SchemaSerializationMode DetermineSchemaSerializationMode (XmlReader reader)
\r
1781 return SchemaSerializationMode.IncludeSchema;
\r
1784 protected SchemaSerializationMode DetermineSchemaSerializationMode (SerializationInfo info, StreamingContext context)
\r
1786 SerializationInfoEnumerator e = info.GetEnumerator ();
\r
1787 while (e.MoveNext ()) {
\r
1788 if (e.Name == "SchemaSerializationMode.DataSet") {
\r
1789 return (SchemaSerializationMode) e.Value;
\r
1793 return SchemaSerializationMode.IncludeSchema;
\r
1796 protected bool IsBinarySerialized (SerializationInfo info, StreamingContext context)
\r
1798 SerializationInfoEnumerator e = info.GetEnumerator ();
\r
1799 while (e.MoveNext ()) {
\r
1800 if (e.ObjectType == typeof (System.Data.SerializationFormat))
\r