2 // System.Data/DataSet.cs
5 // Christopher Podurgiel <cpodurgiel@msn.com>
6 // Daniel Morgan <danmorg@sc.rr.com>
7 // Rodrigo Moya <rodrigo@ximian.com>
8 // Stuart Caborn <stuart.caborn@virgin.net>
9 // Tim Coleman (tim@timcoleman.com)
10 // Ville Palo <vi64pa@koti.soon.fi>
12 // (C) Ximian, Inc. 2002
13 // Copyright (C) Tim Coleman, 2002, 2003
17 using System.Collections;
18 using System.ComponentModel;
19 using System.Globalization;
20 using System.Threading;
22 using System.Runtime.Serialization;
24 using System.Xml.Schema;
25 using System.Xml.Serialization;
26 using System.Data.Common;
28 namespace System.Data {
31 [DefaultProperty ("DataSetName")]
33 public class DataSet : MarshalByValueComponent, IListSource,
34 ISupportInitialize, ISerializable, IXmlSerializable
36 private string dataSetName;
37 private string _namespace = "";
38 private string prefix;
39 private bool caseSensitive;
40 private bool enforceConstraints = true;
41 private DataTableCollection tableCollection;
42 private DataRelationCollection relationCollection;
43 private PropertyCollection properties;
44 private DataViewManager defaultView;
45 private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
49 public DataSet () : this ("NewDataSet")
53 public DataSet (string name)
56 tableCollection = new DataTableCollection (this);
57 relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
58 properties = new PropertyCollection ();
59 this.prefix = String.Empty;
61 this.Locale = CultureInfo.CurrentCulture;
65 protected DataSet (SerializationInfo info, StreamingContext context) : this ()
67 throw new NotImplementedException ();
70 #endregion // Constructors
72 #region Public Properties
74 [DataCategory ("Data")]
75 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
76 [DefaultValue (false)]
77 public bool CaseSensitive {
82 foreach (DataTable T in Tables) {
83 if (T.VirginCaseSensitive)
84 T.CaseSensitive = value;
87 caseSensitive = value;
89 foreach (DataTable table in Tables) {
90 foreach (Constraint c in table.Constraints)
91 c.AssertConstraint ();
97 [DataCategory ("Data")]
98 [DataSysDescription ("The name of this DataSet.")]
100 public string DataSetName {
101 get { return dataSetName; }
102 set { dataSetName = value; }
105 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
107 public DataViewManager DefaultViewManager {
109 if (defaultView == null)
110 defaultView = new DataViewManager (this);
115 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
116 [DefaultValue (true)]
117 public bool EnforceConstraints {
118 get { return enforceConstraints; }
120 if (value != enforceConstraints) {
121 enforceConstraints = value;
123 foreach (DataTable table in Tables) {
124 foreach (Constraint c in table.Constraints)
125 c.AssertConstraint ();
133 [DataCategory ("Data")]
134 [DataSysDescription ("The collection that holds custom user information.")]
135 public PropertyCollection ExtendedProperties {
136 get { return properties; }
140 [DataSysDescription ("Indicates that the DataSet has errors.")]
141 public bool HasErrors {
144 for (int i = 0; i < Tables.Count; i++) {
145 if (Tables[i].HasErrors)
152 [DataCategory ("Data")]
153 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
154 public CultureInfo Locale {
159 if (locale == null || !locale.Equals (value)) {
160 // TODO: check if the new locale is valid
161 // TODO: update locale of all tables
167 public void Merge (DataRow[] rows)
169 Merge (rows, false, MissingSchemaAction.Add);
172 public void Merge (DataSet dataSet)
174 Merge (dataSet, false, MissingSchemaAction.Add);
177 public void Merge (DataTable table)
179 Merge (table, false, MissingSchemaAction.Add);
182 public void Merge (DataSet dataSet, bool preserveChanges)
184 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
188 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
191 throw new ArgumentNullException ("rows");
192 if (!IsLegalSchemaAction (missingSchemaAction))
193 throw new ArgumentOutOfRangeException ("missingSchemaAction");
195 MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
199 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
202 throw new ArgumentNullException ("dataSet");
203 if (!IsLegalSchemaAction (missingSchemaAction))
204 throw new ArgumentOutOfRangeException ("missingSchemaAction");
206 MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
210 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
213 throw new ArgumentNullException ("table");
214 if (!IsLegalSchemaAction (missingSchemaAction))
215 throw new ArgumentOutOfRangeException ("missingSchemaAction");
217 MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
220 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
222 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
223 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
228 [DataCategory ("Data")]
229 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
231 public string Namespace {
233 get { return _namespace; }
236 //TODO - trigger an event if this happens?
241 [DataCategory ("Data")]
242 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
244 public string Prefix {
246 get { return prefix; }
249 //TODO - trigger an event if this happens?
252 value = string.Empty;
254 if (value != this.prefix)
255 RaisePropertyChanging ("Prefix");
260 [DataCategory ("Data")]
261 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
262 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
263 public DataRelationCollection Relations {
265 return relationCollection;
270 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
271 public override ISite Site {
274 throw new NotImplementedException ();
279 throw new NotImplementedException ();
283 [DataCategory ("Data")]
284 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
285 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
286 public DataTableCollection Tables {
287 get { return tableCollection; }
290 #endregion // Public Properties
292 #region Public Methods
295 public void AcceptChanges ()
297 foreach (DataTable tempTable in tableCollection)
298 tempTable.AcceptChanges ();
303 // TODO: if currently bound to a XmlDataDocument
304 // throw a NotSupportedException
305 for (int t = 0; t < tableCollection.Count; t++) {
306 tableCollection[t].Clear ();
310 public virtual DataSet Clone ()
312 DataSet Copy = new DataSet ();
313 CopyProperties (Copy);
315 foreach (DataTable Table in Tables) {
316 Copy.Tables.Add (Table.Clone ());
319 //Copy Relationships between tables after existance of tables
320 //and setting properties correctly
321 CopyRelations (Copy);
326 // Copies both the structure and data for this DataSet.
327 public DataSet Copy ()
329 DataSet Copy = new DataSet ();
330 CopyProperties (Copy);
332 // Copy DatSet's tables
333 foreach (DataTable Table in Tables)
334 Copy.Tables.Add (Table.Copy ());
336 //Copy Relationships between tables after existance of tables
337 //and setting properties correctly
338 CopyRelations (Copy);
344 private void CopyProperties (DataSet Copy)
346 Copy.CaseSensitive = CaseSensitive;
347 //Copy.Container = Container
348 Copy.DataSetName = DataSetName;
349 //Copy.DefaultViewManager
351 Copy.EnforceConstraints = EnforceConstraints;
352 //Copy.ExtendedProperties
354 //Copy.Locale = Locale;
355 Copy.Namespace = Namespace;
356 Copy.Prefix = Prefix;
362 private void CopyRelations (DataSet Copy)
365 //Creation of the relation contains some of the properties, and the constructor
366 //demands these values. instead changing the DataRelation constructor and behaviour the
367 //parameters are pre-configured and sent to the most general constructor
369 foreach (DataRelation MyRelation in this.Relations) {
370 string pTable = MyRelation.ParentTable.TableName;
371 string cTable = MyRelation.ChildTable.TableName;
372 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];
373 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
376 foreach (DataColumn DC in MyRelation.ParentColumns) {
377 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
383 foreach (DataColumn DC in MyRelation.ChildColumns) {
384 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
388 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
389 //cRel.ChildColumns = MyRelation.ChildColumns;
390 //cRel.ChildTable = MyRelation.ChildTable;
391 //cRel.ExtendedProperties = cRel.ExtendedProperties;
392 //cRel.Nested = MyRelation.Nested;
393 //cRel.ParentColumns = MyRelation.ParentColumns;
394 //cRel.ParentTable = MyRelation.ParentTable;
396 Copy.Relations.Add (cRel);
403 public DataSet GetChanges ()
405 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
409 public DataSet GetChanges (DataRowState rowStates)
411 if (!HasChanges (rowStates))
414 DataSet copySet = Clone ();
415 Hashtable addedRows = new Hashtable ();
417 IEnumerator tableEnumerator = Tables.GetEnumerator ();
420 while (tableEnumerator.MoveNext ()) {
421 origTable = (DataTable)tableEnumerator.Current;
422 copyTable = copySet.Tables[origTable.TableName];
424 // Look for relations that have this table as child
425 IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
427 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
428 while (rowEnumerator.MoveNext ()) {
429 DataRow row = (DataRow)rowEnumerator.Current;
431 if (row.IsRowChanged (rowStates))
432 AddChangedRow (addedRows, copySet, copyTable, relations, row);
438 void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
440 if (addedRows.ContainsKey (row)) return;
443 while (relations.MoveNext ()) {
444 DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
445 if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
446 DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
447 AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
450 DataRow newRow = copyTable.NewRow ();
451 copyTable.Rows.Add (newRow);
452 row.CopyValuesToRow (newRow);
453 newRow.XmlRowID = row.XmlRowID;
454 addedRows.Add (row,row);
459 public DataTableReader GetDataReader (DataTable[] dataTables)
461 throw new NotImplementedException ();
465 public DataTableReader GetDataReader ()
467 throw new NotImplementedException ();
471 public string GetXml ()
473 StringWriter Writer = new StringWriter ();
475 // Sending false for not printing the Processing instruction
476 WriteXml (Writer, XmlWriteMode.IgnoreSchema, false);
477 return Writer.ToString ();
480 public string GetXmlSchema ()
482 StringWriter Writer = new StringWriter ();
483 WriteXmlSchema (Writer);
484 return Writer.ToString ();
488 public bool HasChanges ()
490 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
494 public bool HasChanges (DataRowState rowState)
496 if (((int)rowState & 0xffffffe0) != 0)
497 throw new ArgumentOutOfRangeException ("rowState");
499 DataTableCollection tableCollection = Tables;
501 DataRowCollection rowCollection;
504 for (int i = 0; i < tableCollection.Count; i++) {
505 table = tableCollection[i];
506 rowCollection = table.Rows;
507 for (int j = 0; j < rowCollection.Count; j++) {
508 row = rowCollection[j];
509 if ((row.RowState & rowState) != 0)
518 public void InferXmlSchema (XmlReader reader, string[] nsArray)
522 public void InferXmlSchema (Stream stream, string[] nsArray)
524 InferXmlSchema (new XmlTextReader (stream), nsArray);
527 public void InferXmlSchema (TextReader reader, string[] nsArray)
529 InferXmlSchema (new XmlTextReader (reader), nsArray);
532 public void InferXmlSchema (string fileName, string[] nsArray)
534 XmlTextReader reader = new XmlTextReader (fileName);
536 InferXmlSchema (reader, nsArray);
544 public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
546 throw new NotImplementedException ();
550 public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
552 throw new NotImplementedException ();
556 public virtual void RejectChanges ()
559 bool oldEnforceConstraints = this.EnforceConstraints;
560 this.EnforceConstraints = false;
562 for (i = 0; i < this.Tables.Count;i++)
563 this.Tables[i].RejectChanges ();
565 this.EnforceConstraints = oldEnforceConstraints;
568 public virtual void Reset ()
570 IEnumerator constraintEnumerator;
572 // first we remove all ForeignKeyConstraints (if we will not do that
573 // we will get an exception when clearing the tables).
574 for (int i = 0; i < Tables.Count; i++) {
575 ConstraintCollection cc = Tables[i].Constraints;
576 for (int j = 0; j < cc.Count; j++) {
577 if (cc[j] is ForeignKeyConstraint)
587 public void WriteXml (Stream stream)
589 XmlTextWriter writer = new XmlTextWriter (stream, null);
590 writer.Formatting = Formatting.Indented;
595 /// Writes the current data for the DataSet to the specified file.
597 /// <param name="filename">Fully qualified filename to write to</param>
598 public void WriteXml (string fileName)
600 XmlTextWriter writer = new XmlTextWriter (fileName, null);
601 writer.Formatting = Formatting.Indented;
607 public void WriteXml (TextWriter writer)
609 XmlTextWriter xwriter = new XmlTextWriter (writer);
610 xwriter.Formatting = Formatting.Indented;
614 public void WriteXml (XmlWriter writer)
616 WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
619 public void WriteXml (string filename, XmlWriteMode mode)
621 XmlTextWriter writer = new XmlTextWriter (filename, null);
622 writer.Formatting = Formatting.Indented;
623 WriteXml (writer, mode, true);
626 public void WriteXml (Stream stream, XmlWriteMode mode)
628 XmlTextWriter writer = new XmlTextWriter (stream, null);
629 writer.Formatting = Formatting.Indented;
630 WriteXml (writer, mode, true);
633 public void WriteXml (TextWriter writer, XmlWriteMode mode)
635 XmlTextWriter xwriter = new XmlTextWriter (writer);
636 xwriter.Formatting = Formatting.Indented;
637 WriteXml (xwriter, mode, true);
640 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
642 WriteXml (writer, mode, true);
645 internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
647 XmlTextWriter writer = new XmlTextWriter (stream, null);
648 writer.Formatting = Formatting.Indented;
649 WriteXml (writer, mode, writePI);
652 internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
654 XmlTextWriter writer = new XmlTextWriter (fileName, null);
655 writer.Formatting = Formatting.Indented;
656 WriteXml (writer, mode, writePI);
661 internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
663 XmlTextWriter xwriter = new XmlTextWriter (writer);
664 xwriter.Formatting = Formatting.Indented;
665 WriteXml (xwriter, mode, writePI);
668 internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
670 if (writePI && (writer.WriteState == WriteState.Start))
671 writer.WriteStartDocument (true);
673 if (mode == XmlWriteMode.DiffGram) {
675 WriteDiffGramElement(writer);
678 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
680 /*********************************************************
681 * This is a patch for interoperability with ms.net. *
682 * Because in web services the .net client expects this *
683 * atrribute even if namespace is an empty string *
684 ********************************************************/
685 if (Namespace == null || Namespace.Length == 0)
686 WriteAttributeString (writer, mode, null, null, "xmlns", Namespace);
689 if (mode == XmlWriteMode.WriteSchema) {
690 DoWriteXmlSchema (writer);
693 WriteTables (writer, mode, Tables, DataRowVersion.Default);
694 if (mode == XmlWriteMode.DiffGram) {
695 writer.WriteEndElement (); //DataSet name
696 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
698 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
699 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
700 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
701 writer.WriteEndElement ();
704 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
707 public void WriteXmlSchema (Stream stream)
709 XmlTextWriter writer = new XmlTextWriter (stream, null );
710 writer.Formatting = Formatting.Indented;
711 WriteXmlSchema (writer);
714 public void WriteXmlSchema (string fileName)
716 XmlTextWriter writer = new XmlTextWriter (fileName, null);
717 writer.Formatting = Formatting.Indented;
718 WriteXmlSchema (writer);
721 public void WriteXmlSchema (TextWriter writer)
723 XmlTextWriter xwriter = new XmlTextWriter (writer);
724 xwriter.Formatting = Formatting.Indented;
725 WriteXmlSchema (xwriter);
728 public void WriteXmlSchema (XmlWriter writer)
730 //Create a skeleton doc and then write the schema
731 //proper which is common to the WriteXml method in schema mode
732 writer.WriteStartDocument ();
733 DoWriteXmlSchema (writer);
735 writer.WriteEndDocument ();
738 public void ReadXmlSchema (Stream stream)
740 XmlReader reader = new XmlTextReader (stream, null);
741 ReadXmlSchema (reader);
744 public void ReadXmlSchema (string str)
746 XmlReader reader = new XmlTextReader (str);
747 ReadXmlSchema (reader);
750 public void ReadXmlSchema (TextReader treader)
752 XmlReader reader = new XmlTextReader (treader);
753 ReadXmlSchema (reader);
756 public void ReadXmlSchema (XmlReader reader)
758 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
759 SchemaMapper.Read (reader);
762 public XmlReadMode ReadXml (Stream stream)
764 return ReadXml (new XmlTextReader (stream));
767 public XmlReadMode ReadXml (string str)
769 return ReadXml (new XmlTextReader (str));
772 public XmlReadMode ReadXml (TextReader reader)
774 return ReadXml (new XmlTextReader (reader));
777 public XmlReadMode ReadXml (XmlReader r)
779 XmlDataLoader Loader = new XmlDataLoader (this);
780 // FIXME: somekinda exception?
782 return XmlReadMode.Auto; // FIXME
784 // Check if the curent element is the process instruction (PI).
785 // if it is move to next element.
786 if (r.LocalName == "xml")
789 // The document can be diffgram if :
790 // 1. The first element is diffgram.
791 if (r.LocalName == "diffgram") {
792 return ReadXml (r, XmlReadMode.DiffGram);
795 bool schemaRead = false;
796 if (r.LocalName == "schema") {
802 // If we read the schema the next element can be a diffgram
803 // that is what happen in web services soap message.
804 if (schemaRead && r.LocalName == "diffgram") {
805 return ReadXml (r, XmlReadMode.DiffGram);
808 // Get the DataSet name.
809 // if this xml is not diffgram then the first element will be the
811 string dataSetName = XmlConvert.DecodeName (r.LocalName);
812 DataSetName = dataSetName;
814 r.ReadStartElement ();
818 // After reading the dataset name there can be three scenarios:
819 // 1. The next part will be the schema of the dataset.
820 // 2. The next part will be the data of the dataset using diffgram.
821 // 3. The next part will be the data of tha dataset without diffgram.
822 // Check if the current element is the schema
823 if (r.LocalName == "schema") {
829 // check if the data was written in a diffgram mode.
830 if (r.LocalName == "diffgram") {
831 return ReadXml (r, XmlReadMode.DiffGram);
834 // If the schema has been read we should read the rest data of the dataset
835 // with ignoreschema mode.
837 ReadXml (r, XmlReadMode.IgnoreSchema, false);
838 return XmlReadMode.ReadSchema;
841 // Read the data of the dataset with inferschema.
842 return ReadXml (r, XmlReadMode.InferSchema, false);
846 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
848 return ReadXml (new XmlTextReader (stream), mode);
851 public XmlReadMode ReadXml (string str, XmlReadMode mode)
853 return ReadXml (new XmlTextReader (str), mode);
856 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
858 return ReadXml (new XmlTextReader (reader), mode);
862 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
864 // we have to initiate the reader.
865 if (reader.ReadState == ReadState.Initial)
868 // Check if the curent element is the process instruction (PI).
869 // if it is move to next element.
870 if (reader.LocalName == "xml")
871 reader.MoveToContent();
873 XmlReadMode Result = XmlReadMode.Auto;
875 if (mode == XmlReadMode.DiffGram) {
876 if (reader.LocalName != "diffgram"){
877 reader.MoveToContent ();
878 reader.ReadStartElement (); // <DataSet>
880 reader.MoveToContent ();
881 if (reader.LocalName == "schema")
882 ReadXmlSchema (reader);
884 reader.MoveToContent ();
886 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
887 DiffLoader.Load (reader);
888 Result = XmlReadMode.DiffGram;
891 Result = ReadXml(reader, mode, true);
896 private XmlReadMode ReadXml (XmlReader r, XmlReadMode mode, bool readDataSet) {
899 string dataSetName = XmlConvert.DecodeName (r.LocalName);
900 DataSetName = dataSetName;
901 // get the Namespace of the DataSet.
902 string tmp = r.GetAttribute("xmlns");
906 r.ReadStartElement ();
910 XmlDataLoader Loader = new XmlDataLoader (this);
911 return Loader.LoadData (r, mode);
914 #endregion // Public Methods
916 #region Public Events
918 [DataCategory ("Action")]
919 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
920 public event MergeFailedEventHandler MergeFailed;
922 #endregion // Public Events
930 #endregion Destructors
932 #region IListSource methods
933 IList IListSource.GetList ()
935 return DefaultViewManager;
938 bool IListSource.ContainsListCollection {
943 #endregion IListSource methods
945 #region ISupportInitialize methods
946 public void BeginInit ()
950 public void EndInit ()
955 #region ISerializable
956 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
958 throw new NotImplementedException ();
962 #region Protected Methods
963 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
965 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
966 if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s)));
970 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
975 protected virtual void ReadXmlSerializable (XmlReader reader)
977 ReadXml (reader, XmlReadMode.DiffGram); // FIXME
980 void IXmlSerializable.ReadXml (XmlReader reader)
983 ReadXmlSerializable(reader);
985 // the XmlSerializationReader does this lines!!!
986 //reader.MoveToContent ();
987 //reader.ReadEndElement (); // </DataSet>
990 void IXmlSerializable.WriteXml (XmlWriter writer)
992 DoWriteXmlSchema (writer);
993 WriteXml (writer, XmlWriteMode.DiffGram, true);
996 protected virtual bool ShouldSerializeRelations ()
1001 protected virtual bool ShouldSerializeTables ()
1007 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
1012 protected virtual void OnRemoveRelation (DataRelation relation)
1017 protected virtual void OnRemoveTable (DataTable table)
1021 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
1023 if (MergeFailed != null)
1024 MergeFailed (this, e);
1028 protected internal void RaisePropertyChanging (string name)
1033 #region Private Xml Serialisation
1035 private string WriteObjectXml (object o)
1037 switch (Type.GetTypeCode (o.GetType ())) {
1038 case TypeCode.Boolean:
1039 return XmlConvert.ToString ((Boolean) o);
1041 return XmlConvert.ToString ((Byte) o);
1043 return XmlConvert.ToString ((Char) o);
1044 case TypeCode.DateTime:
1045 return XmlConvert.ToString ((DateTime) o);
1046 case TypeCode.Decimal:
1047 return XmlConvert.ToString ((Decimal) o);
1048 case TypeCode.Double:
1049 return XmlConvert.ToString ((Double) o);
1050 case TypeCode.Int16:
1051 return XmlConvert.ToString ((Int16) o);
1052 case TypeCode.Int32:
1053 return XmlConvert.ToString ((Int32) o);
1054 case TypeCode.Int64:
1055 return XmlConvert.ToString ((Int64) o);
1056 case TypeCode.SByte:
1057 return XmlConvert.ToString ((SByte) o);
1058 case TypeCode.Single:
1059 return XmlConvert.ToString ((Single) o);
1060 case TypeCode.UInt16:
1061 return XmlConvert.ToString ((UInt16) o);
1062 case TypeCode.UInt32:
1063 return XmlConvert.ToString ((UInt32) o);
1064 case TypeCode.UInt64:
1065 return XmlConvert.ToString ((UInt64) o);
1067 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
1068 if (o is Guid) return XmlConvert.ToString ((Guid) o);
1069 return o.ToString ();
1072 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
1074 //Write out each table in order, providing it is not
1075 //part of another table structure via a nested parent relationship
1076 foreach (DataTable table in tableCollection) {
1077 bool isTopLevel = true;
1078 foreach (DataRelation rel in table.ParentRelations) {
1086 WriteTable ( writer, table, mode, version);
1091 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
1093 DataRow[] rows = new DataRow [table.Rows.Count];
1094 table.Rows.CopyTo (rows, 0);
1095 WriteTable (writer, rows, mode, version);
1098 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1100 //The columns can be attributes, hidden, elements, or simple content
1101 //There can be 0-1 simple content cols or 0-* elements
1102 System.Collections.ArrayList atts;
1103 System.Collections.ArrayList elements;
1104 DataColumn simple = null;
1106 if (rows.Length == 0) return;
1107 DataTable table = rows[0].Table;
1108 SplitColumns (table, out atts, out elements, out simple);
1109 //sort out the namespacing
1110 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1112 foreach (DataRow row in rows) {
1113 if (!row.HasVersion(version) ||
1114 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
1115 && version == DataRowVersion.Original))
1118 // First check are all the rows null. If they are we just write empty element
1119 bool AllNulls = true;
1120 foreach (DataColumn dc in table.Columns) {
1122 if (row [dc.ColumnName, version] != DBNull.Value) {
1128 // If all of the columns were null, we have to write empty element
1130 writer.WriteElementString (table.TableName, "");
1134 WriteTableElement (writer, mode, table, row, version);
1136 foreach (DataColumn col in atts) {
1137 WriteColumnAsAttribute (writer, mode, col, row, version);
1140 if (simple != null) {
1141 writer.WriteString (WriteObjectXml (row[simple, version]));
1144 foreach (DataColumn col in elements) {
1145 WriteColumnAsElement (writer, mode, nspc, col, row, version);
1149 foreach (DataRelation relation in table.ChildRelations) {
1150 if (relation.Nested) {
1151 WriteTable (writer, row.GetChildRows (relation), mode, version);
1155 writer.WriteEndElement ();
1160 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
1162 string colnspc = nspc;
1163 object rowObject = row [col, version];
1165 if (rowObject == null || rowObject == DBNull.Value)
1168 if (col.Namespace != null) {
1169 colnspc = col.Namespace;
1172 //TODO check if I can get away with write element string
1173 WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName);
1174 writer.WriteString (WriteObjectXml (rowObject));
1175 writer.WriteEndElement ();
1178 private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1180 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
1183 private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
1185 //sort out the namespacing
1186 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1188 WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
1190 if (mode == XmlWriteMode.DiffGram) {
1191 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
1192 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", row.XmlRowID.ToString());
1193 string modeName = null;
1194 if (row.RowState == DataRowState.Modified)
1195 modeName = "modified";
1196 else if (row.RowState == DataRowState.Added)
1197 modeName = "inserted";
1199 if (version != DataRowVersion.Original && modeName != null)
1200 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
1204 private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
1206 if (nspc == null || nspc == "") {
1207 writer.WriteStartElement (name);
1209 else if (prefix != null) {
1210 writer.WriteStartElement (prefix, name, nspc);
1213 writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
1217 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1220 case XmlWriteMode.WriteSchema:
1221 writer.WriteAttributeString (prefix, name, nspc);
1223 case XmlWriteMode.DiffGram:
1224 writer.WriteAttributeString (prefix, name, nspc,stringValue);
1227 writer.WriteAttributeString (name, stringValue);
1232 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
1234 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
1236 if (mode == XmlWriteMode.DiffGram) {
1237 SetTableRowsID (table);
1238 WriteDiffGramElement (writer);
1241 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
1243 WriteTable (writer, table, mode, DataRowVersion.Default);
1245 if (mode == XmlWriteMode.DiffGram) {
1246 writer.WriteEndElement (); //DataSet name
1247 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
1249 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
1250 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
1251 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
1252 writer.WriteEndElement ();
1255 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
1258 XmlSchema IXmlSerializable.GetSchema ()
1260 return BuildSchema ();
1263 XmlSchema BuildSchema ()
1265 return BuildSchema (Tables, Relations);
1268 internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
1270 string constraintPrefix = "";
1271 XmlSchema schema = new XmlSchema ();
1273 schema.Namespaces.Add("xs", XmlSchema.Namespace);
1274 schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1276 if (Namespace != "" && Namespace != null) {
1277 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1278 schema.ElementFormDefault = XmlSchemaForm.Qualified;
1279 schema.TargetNamespace = Namespace;
1280 schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
1281 constraintPrefix = XmlConstants.TnsPrefix + ":";
1284 // set the schema id
1285 schema.Id = DataSetName;
1286 XmlDocument doc = new XmlDocument ();
1287 XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
1288 xmlnsAttr.Value = Namespace;
1290 schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
1292 XmlSchemaElement elem = new XmlSchemaElement ();
1293 elem.Name = XmlConvert.EncodeName (DataSetName);
1295 XmlAttribute[] atts = new XmlAttribute [2];
1296 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1297 atts[0].Value = "true";
1299 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1300 atts[1].Value = locale.Name;
1301 elem.UnhandledAttributes = atts;
1303 schema.Items.Add (elem);
1305 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1306 elem.SchemaType = complex;
1308 XmlSchemaChoice choice = new XmlSchemaChoice ();
1309 complex.Particle = choice;
1310 choice.MaxOccursString = XmlConstants.Unbounded;
1312 //Write out schema for each table in order
1313 foreach (DataTable table in tables) {
1314 bool isTopLevel = true;
1315 foreach (DataRelation rel in table.ParentRelations) {
1323 choice.Items.Add (GetTableSchema (doc, table));
1327 AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
1331 // Add all constraints in all tables to the schema.
1332 private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
1334 // first add all unique constraints.
1335 Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
1336 // Add all foriegn key constraints.
1337 AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
1340 // Add unique constaraints to the schema.
1341 // return hashtable with the names of all XmlSchemaUnique elements we created.
1342 private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
1344 XmlDocument doc = new XmlDocument();
1345 Hashtable uniqueNames = new Hashtable();
1346 foreach (DataTable table in tables) {
1348 foreach (Constraint constaint in table.Constraints) {
1350 if (constaint is UniqueConstraint) {
1351 ArrayList attrs = new ArrayList ();
1352 XmlAttribute attrib;
1353 UniqueConstraint uqConst = (UniqueConstraint)constaint;
1354 XmlSchemaUnique uniq = new XmlSchemaUnique ();
1356 // if column of the constraint is hidden do not write the constraint.
1357 bool isHidden = false;
1358 foreach (DataColumn column in uqConst.Columns) {
1359 if (column.ColumnMapping == MappingType.Hidden) {
1368 // if constaraint name do not exist in the hashtable we can use it.
1369 if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
1370 uniq.Name = uqConst.ConstraintName;
1372 // generate new constraint name for the XmlSchemaUnique element.
1374 uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
1375 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1376 attrib.Value = uqConst.ConstraintName;
1379 if (uqConst.IsPrimaryKey) {
1380 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
1381 attrib.Value = "true";
1385 uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1387 uniq.Selector = new XmlSchemaXPath();
1388 uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
1389 XmlSchemaXPath field;
1390 foreach (DataColumn column in uqConst.Columns) {
1391 field = new XmlSchemaXPath();
1392 field.XPath = constraintPrefix+column.ColumnName;
1393 uniq.Fields.Add(field);
1396 elem.Constraints.Add (uniq);
1397 uniqueNames.Add (uniq.Name, null);
1404 // Add the foriegn keys to the schema.
1405 private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
1407 if (relations == null) return;
1409 XmlDocument doc = new XmlDocument();
1410 foreach (DataRelation rel in relations) {
1412 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
1415 ArrayList attrs = new ArrayList ();
1416 XmlAttribute attrib;
1417 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1418 keyRef.Name = rel.RelationName;
1419 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1420 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1422 string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
1423 // first try to find the concatenated name. If we didn't find it - use constraint name.
1424 if (uniqueNames.ContainsKey (concatName)) {
1425 keyRef.Refer = new XmlQualifiedName(concatName);
1428 keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
1432 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1433 attrib.Value = "true";
1437 keyRef.Selector = new XmlSchemaXPath();
1438 keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
1439 XmlSchemaXPath field;
1440 foreach (DataColumn column in rel.ChildColumns) {
1441 field = new XmlSchemaXPath();
1442 field.XPath = constraintPrefix+column.ColumnName;
1443 keyRef.Fields.Add(field);
1445 keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1446 elem.Constraints.Add (keyRef);
1450 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1456 SplitColumns (table, out atts, out elements, out simple);
1458 XmlSchemaElement elem = new XmlSchemaElement ();
1459 elem.Name = table.TableName;
1461 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1462 elem.SchemaType = complex;
1464 //TODO - what about the simple content?
1465 if (simple != null) {
1466 // add simpleContent
1467 XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
1468 complex.ContentModel = simpleContent;
1470 // add column name attribute
1471 XmlAttribute[] xlmAttrs = new XmlAttribute [2];
1472 xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
1473 xlmAttrs[0].Value = simple.ColumnName;
1475 // add ordinal attribute
1476 xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
1477 xlmAttrs[1].Value = simple.Ordinal.ToString();
1478 simpleContent.UnhandledAttributes = xlmAttrs;
1482 XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
1483 simpleContent.Content = extension;
1484 extension.BaseTypeName = MapType (simple.DataType);
1488 //A sequence of element types or a simple content node
1490 XmlSchemaSequence seq = new XmlSchemaSequence ();
1491 complex.Particle = seq;
1493 foreach (DataColumn col in elements) {
1494 //<xs:element name=ColumnName type=MappedType Ordinal=index>
1495 XmlSchemaElement colElem = new XmlSchemaElement ();
1496 ArrayList xattrs = new ArrayList();
1498 colElem.Name = col.ColumnName;
1500 if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
1501 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1502 xattr.Value = col.Caption;
1506 if (col.AutoIncrement == true) {
1507 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
1508 xattr.Value = "true";
1512 if (col.AutoIncrementSeed != 0) {
1513 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
1514 xattr.Value = col.AutoIncrementSeed.ToString();
1518 if (col.DefaultValue.ToString () != String.Empty)
1519 colElem.DefaultValue = col.DefaultValue.ToString ();
1521 if (col.MaxLength < 0)
1522 colElem.SchemaTypeName = MapType (col.DataType);
1524 if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string)
1525 && col.DataType != typeof (char)) {
1526 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
1527 xattr.Value = col.DataType.ToString();
1531 if (col.AllowDBNull) {
1532 colElem.MinOccurs = 0;
1535 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
1536 // XmlConstants.Ordinal,
1537 // XmlConstants.MsdataNamespace,
1538 // col.Ordinal.ToString ());
1540 // Write SimpleType if column have MaxLength
1541 if (col.MaxLength > -1) {
1542 colElem.SchemaType = GetTableSimpleType (doc, col);
1545 colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
1546 seq.Items.Add (colElem);
1549 foreach (DataRelation rel in table.ChildRelations) {
1551 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1556 //Then a list of attributes
1557 foreach (DataColumn col in atts) {
1558 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1559 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1560 att.Name = col.ColumnName;
1561 att.Form = XmlSchemaForm.Unqualified;
1562 att.SchemaTypeName = MapType (col.DataType);
1563 complex.Attributes.Add (att);
1569 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1572 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1575 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1576 restriction.BaseTypeName = MapType (col.DataType);
1579 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1580 max.Value = XmlConvert.ToString (col.MaxLength);
1581 restriction.Facets.Add (max);
1583 simple.Content = restriction;
1587 private void DoWriteXmlSchema (XmlWriter writer)
1589 BuildSchema ().Write (writer);
1593 /// Helper function to split columns into attributes elements and simple
1596 private void SplitColumns (DataTable table,
1598 out ArrayList elements,
1599 out DataColumn simple)
1601 //The columns can be attributes, hidden, elements, or simple content
1602 //There can be 0-1 simple content cols or 0-* elements
1603 atts = new System.Collections.ArrayList ();
1604 elements = new System.Collections.ArrayList ();
1607 //Sort out the columns
1608 foreach (DataColumn col in table.Columns) {
1609 switch (col.ColumnMapping) {
1610 case MappingType.Attribute:
1613 case MappingType.Element:
1616 case MappingType.SimpleContent:
1617 if (simple != null) {
1618 throw new System.InvalidOperationException ("There may only be one simple content element");
1623 //ignore Hidden elements
1629 private void WriteDiffGramElement(XmlWriter writer)
1631 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
1632 WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1635 private void SetRowsID()
1637 foreach (DataTable Table in Tables)
1638 SetTableRowsID (Table);
1641 private void SetTableRowsID (DataTable Table)
1644 foreach (DataRow Row in Table.Rows) {
1645 Row.XmlRowID = dataRowID;
1651 private XmlQualifiedName MapType (Type type)
1653 switch (Type.GetTypeCode (type)) {
1654 case TypeCode.String: return XmlConstants.QnString;
1655 case TypeCode.Int16: return XmlConstants.QnShort;
1656 case TypeCode.Int32: return XmlConstants.QnInt;
1657 case TypeCode.Int64: return XmlConstants.QnLong;
1658 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1659 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1660 //case TypeCode.Char: return XmlConstants.QnChar;
1661 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1662 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1663 case TypeCode.Double: return XmlConstants.QnDouble;
1664 case TypeCode.SByte: return XmlConstants.QnSbyte;
1665 case TypeCode.Single: return XmlConstants.QnFloat;
1666 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1667 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1668 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1671 if (typeof (TimeSpan) == type)
1672 return XmlConstants.QnDuration;
1673 else if (typeof (System.Uri) == type)
1674 return XmlConstants.QnUri;
1675 else if (typeof (byte[]) == type)
1676 return XmlConstants.QnBase64Binary;
1677 else if (typeof (XmlQualifiedName) == type)
1678 return XmlConstants.QnXmlQualifiedName;
1680 return XmlConstants.QnString;
1683 #endregion //Private Xml Serialisation