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 // first assert all unique constraints
125 foreach (UniqueConstraint uc in table.Constraints.UniqueConstraints)
126 uc.AssertConstraint ();
127 // then assert all foreign keys
128 foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
129 fk.AssertConstraint ();
137 [DataCategory ("Data")]
138 [DataSysDescription ("The collection that holds custom user information.")]
139 public PropertyCollection ExtendedProperties {
140 get { return properties; }
144 [DataSysDescription ("Indicates that the DataSet has errors.")]
145 public bool HasErrors {
148 for (int i = 0; i < Tables.Count; i++) {
149 if (Tables[i].HasErrors)
156 [DataCategory ("Data")]
157 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
158 public CultureInfo Locale {
163 if (locale == null || !locale.Equals (value)) {
164 // TODO: check if the new locale is valid
165 // TODO: update locale of all tables
171 public void Merge (DataRow[] rows)
173 Merge (rows, false, MissingSchemaAction.Add);
176 public void Merge (DataSet dataSet)
178 Merge (dataSet, false, MissingSchemaAction.Add);
181 public void Merge (DataTable table)
183 Merge (table, false, MissingSchemaAction.Add);
186 public void Merge (DataSet dataSet, bool preserveChanges)
188 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
192 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
195 throw new ArgumentNullException ("rows");
196 if (!IsLegalSchemaAction (missingSchemaAction))
197 throw new ArgumentOutOfRangeException ("missingSchemaAction");
199 MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
203 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
206 throw new ArgumentNullException ("dataSet");
207 if (!IsLegalSchemaAction (missingSchemaAction))
208 throw new ArgumentOutOfRangeException ("missingSchemaAction");
210 MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
214 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
217 throw new ArgumentNullException ("table");
218 if (!IsLegalSchemaAction (missingSchemaAction))
219 throw new ArgumentOutOfRangeException ("missingSchemaAction");
221 MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
224 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
226 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
227 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
232 [DataCategory ("Data")]
233 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
235 public string Namespace {
237 get { return _namespace; }
240 //TODO - trigger an event if this happens?
245 [DataCategory ("Data")]
246 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
248 public string Prefix {
250 get { return prefix; }
253 //TODO - trigger an event if this happens?
256 value = string.Empty;
258 if (value != this.prefix)
259 RaisePropertyChanging ("Prefix");
264 [DataCategory ("Data")]
265 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
266 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
267 public DataRelationCollection Relations {
269 return relationCollection;
274 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
275 public override ISite Site {
278 throw new NotImplementedException ();
283 throw new NotImplementedException ();
287 [DataCategory ("Data")]
288 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
289 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
290 public DataTableCollection Tables {
291 get { return tableCollection; }
294 #endregion // Public Properties
296 #region Public Methods
299 public void AcceptChanges ()
301 foreach (DataTable tempTable in tableCollection)
302 tempTable.AcceptChanges ();
307 // TODO: if currently bound to a XmlDataDocument
308 // throw a NotSupportedException
309 for (int t = 0; t < tableCollection.Count; t++) {
310 tableCollection[t].Clear ();
314 public virtual DataSet Clone ()
316 DataSet Copy = new DataSet ();
317 CopyProperties (Copy);
319 foreach (DataTable Table in Tables) {
320 Copy.Tables.Add (Table.Clone ());
323 //Copy Relationships between tables after existance of tables
324 //and setting properties correctly
325 CopyRelations (Copy);
330 // Copies both the structure and data for this DataSet.
331 public DataSet Copy ()
333 DataSet Copy = new DataSet ();
334 CopyProperties (Copy);
336 // Copy DatSet's tables
337 foreach (DataTable Table in Tables)
338 Copy.Tables.Add (Table.Copy ());
340 //Copy Relationships between tables after existance of tables
341 //and setting properties correctly
342 CopyRelations (Copy);
348 private void CopyProperties (DataSet Copy)
350 Copy.CaseSensitive = CaseSensitive;
351 //Copy.Container = Container
352 Copy.DataSetName = DataSetName;
353 //Copy.DefaultViewManager
355 Copy.EnforceConstraints = EnforceConstraints;
356 //Copy.ExtendedProperties
358 //Copy.Locale = Locale;
359 Copy.Namespace = Namespace;
360 Copy.Prefix = Prefix;
366 private void CopyRelations (DataSet Copy)
369 //Creation of the relation contains some of the properties, and the constructor
370 //demands these values. instead changing the DataRelation constructor and behaviour the
371 //parameters are pre-configured and sent to the most general constructor
373 foreach (DataRelation MyRelation in this.Relations) {
374 string pTable = MyRelation.ParentTable.TableName;
375 string cTable = MyRelation.ChildTable.TableName;
376 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];
377 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
380 foreach (DataColumn DC in MyRelation.ParentColumns) {
381 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
387 foreach (DataColumn DC in MyRelation.ChildColumns) {
388 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
392 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
393 //cRel.ChildColumns = MyRelation.ChildColumns;
394 //cRel.ChildTable = MyRelation.ChildTable;
395 //cRel.ExtendedProperties = cRel.ExtendedProperties;
396 //cRel.Nested = MyRelation.Nested;
397 //cRel.ParentColumns = MyRelation.ParentColumns;
398 //cRel.ParentTable = MyRelation.ParentTable;
400 Copy.Relations.Add (cRel);
407 public DataSet GetChanges ()
409 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
413 public DataSet GetChanges (DataRowState rowStates)
415 if (!HasChanges (rowStates))
418 DataSet copySet = Clone ();
419 Hashtable addedRows = new Hashtable ();
421 IEnumerator tableEnumerator = Tables.GetEnumerator ();
424 while (tableEnumerator.MoveNext ()) {
425 origTable = (DataTable)tableEnumerator.Current;
426 copyTable = copySet.Tables[origTable.TableName];
428 // Look for relations that have this table as child
429 IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
431 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
432 while (rowEnumerator.MoveNext ()) {
433 DataRow row = (DataRow)rowEnumerator.Current;
435 if (row.IsRowChanged (rowStates))
436 AddChangedRow (addedRows, copySet, copyTable, relations, row);
442 void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
444 if (addedRows.ContainsKey (row)) return;
447 while (relations.MoveNext ()) {
448 DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
449 if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
450 DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
451 AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
454 DataRow newRow = copyTable.NewRow ();
455 copyTable.Rows.Add (newRow);
456 row.CopyValuesToRow (newRow);
457 newRow.XmlRowID = row.XmlRowID;
458 addedRows.Add (row,row);
463 public DataTableReader GetDataReader (DataTable[] dataTables)
465 throw new NotImplementedException ();
469 public DataTableReader GetDataReader ()
471 throw new NotImplementedException ();
475 public string GetXml ()
477 StringWriter Writer = new StringWriter ();
479 // Sending false for not printing the Processing instruction
480 WriteXml (Writer, XmlWriteMode.IgnoreSchema, false);
481 return Writer.ToString ();
484 public string GetXmlSchema ()
486 StringWriter Writer = new StringWriter ();
487 WriteXmlSchema (Writer);
488 return Writer.ToString ();
492 public bool HasChanges ()
494 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
498 public bool HasChanges (DataRowState rowState)
500 if (((int)rowState & 0xffffffe0) != 0)
501 throw new ArgumentOutOfRangeException ("rowState");
503 DataTableCollection tableCollection = Tables;
505 DataRowCollection rowCollection;
508 for (int i = 0; i < tableCollection.Count; i++) {
509 table = tableCollection[i];
510 rowCollection = table.Rows;
511 for (int j = 0; j < rowCollection.Count; j++) {
512 row = rowCollection[j];
513 if ((row.RowState & rowState) != 0)
522 public void InferXmlSchema (XmlReader reader, string[] nsArray)
526 public void InferXmlSchema (Stream stream, string[] nsArray)
528 InferXmlSchema (new XmlTextReader (stream), nsArray);
531 public void InferXmlSchema (TextReader reader, string[] nsArray)
533 InferXmlSchema (new XmlTextReader (reader), nsArray);
536 public void InferXmlSchema (string fileName, string[] nsArray)
538 XmlTextReader reader = new XmlTextReader (fileName);
540 InferXmlSchema (reader, nsArray);
548 public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
550 throw new NotImplementedException ();
554 public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
556 throw new NotImplementedException ();
560 public virtual void RejectChanges ()
563 bool oldEnforceConstraints = this.EnforceConstraints;
564 this.EnforceConstraints = false;
566 for (i = 0; i < this.Tables.Count;i++)
567 this.Tables[i].RejectChanges ();
569 this.EnforceConstraints = oldEnforceConstraints;
572 public virtual void Reset ()
574 IEnumerator constraintEnumerator;
576 // first we remove all ForeignKeyConstraints (if we will not do that
577 // we will get an exception when clearing the tables).
578 for (int i = 0; i < Tables.Count; i++) {
579 ConstraintCollection cc = Tables[i].Constraints;
580 for (int j = 0; j < cc.Count; j++) {
581 if (cc[j] is ForeignKeyConstraint)
591 public void WriteXml (Stream stream)
593 XmlTextWriter writer = new XmlTextWriter (stream, null);
594 writer.Formatting = Formatting.Indented;
599 /// Writes the current data for the DataSet to the specified file.
601 /// <param name="filename">Fully qualified filename to write to</param>
602 public void WriteXml (string fileName)
604 XmlTextWriter writer = new XmlTextWriter (fileName, null);
605 writer.Formatting = Formatting.Indented;
615 public void WriteXml (TextWriter writer)
617 XmlTextWriter xwriter = new XmlTextWriter (writer);
618 xwriter.Formatting = Formatting.Indented;
622 public void WriteXml (XmlWriter writer)
624 WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
627 public void WriteXml (string filename, XmlWriteMode mode)
629 XmlTextWriter writer = new XmlTextWriter (filename, null);
630 writer.Formatting = Formatting.Indented;
633 WriteXml (writer, mode, true);
640 public void WriteXml (Stream stream, XmlWriteMode mode)
642 XmlTextWriter writer = new XmlTextWriter (stream, null);
643 writer.Formatting = Formatting.Indented;
644 WriteXml (writer, mode, true);
647 public void WriteXml (TextWriter writer, XmlWriteMode mode)
649 XmlTextWriter xwriter = new XmlTextWriter (writer);
650 xwriter.Formatting = Formatting.Indented;
651 WriteXml (xwriter, mode, true);
654 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
656 WriteXml (writer, mode, true);
659 internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
661 XmlTextWriter writer = new XmlTextWriter (stream, null);
662 writer.Formatting = Formatting.Indented;
663 WriteXml (writer, mode, writePI);
666 internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
668 XmlTextWriter writer = new XmlTextWriter (fileName, null);
669 writer.Formatting = Formatting.Indented;
672 WriteXml (writer, mode, writePI);
679 internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
681 XmlTextWriter xwriter = new XmlTextWriter (writer);
682 xwriter.Formatting = Formatting.Indented;
683 WriteXml (xwriter, mode, writePI);
686 internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
688 if (writePI && (writer.WriteState == WriteState.Start))
689 writer.WriteStartDocument (true);
691 if (mode == XmlWriteMode.DiffGram) {
693 WriteDiffGramElement(writer);
696 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
698 /*********************************************************
699 * This is a patch for interoperability with ms.net. *
700 * Because in web services the .net client expects this *
701 * atrribute even if namespace is an empty string *
702 ********************************************************/
703 if (Namespace == null || Namespace.Length == 0)
704 WriteAttributeString (writer, mode, null, null, "xmlns", Namespace);
706 if (mode == XmlWriteMode.WriteSchema) {
707 DoWriteXmlSchema (writer);
710 WriteTables (writer, mode, Tables, DataRowVersion.Default);
711 if (mode == XmlWriteMode.DiffGram) {
712 writer.WriteEndElement (); //DataSet name
713 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
715 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
716 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
717 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
718 writer.WriteEndElement ();
721 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
724 public void WriteXmlSchema (Stream stream)
726 XmlTextWriter writer = new XmlTextWriter (stream, null );
727 writer.Formatting = Formatting.Indented;
728 WriteXmlSchema (writer);
731 public void WriteXmlSchema (string fileName)
733 XmlTextWriter writer = new XmlTextWriter (fileName, null);
734 writer.Formatting = Formatting.Indented;
736 WriteXmlSchema (writer);
743 public void WriteXmlSchema (TextWriter writer)
745 XmlTextWriter xwriter = new XmlTextWriter (writer);
746 xwriter.Formatting = Formatting.Indented;
747 WriteXmlSchema (xwriter);
750 public void WriteXmlSchema (XmlWriter writer)
752 //Create a skeleton doc and then write the schema
753 //proper which is common to the WriteXml method in schema mode
754 writer.WriteStartDocument ();
755 DoWriteXmlSchema (writer);
757 writer.WriteEndDocument ();
760 public void ReadXmlSchema (Stream stream)
762 XmlReader reader = new XmlTextReader (stream, null);
763 ReadXmlSchema (reader);
766 public void ReadXmlSchema (string str)
768 XmlReader reader = new XmlTextReader (str);
770 ReadXmlSchema (reader);
777 public void ReadXmlSchema (TextReader treader)
779 XmlReader reader = new XmlTextReader (treader);
780 ReadXmlSchema (reader);
783 public void ReadXmlSchema (XmlReader reader)
785 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
786 SchemaMapper.Read (reader);
789 public XmlReadMode ReadXml (Stream stream)
791 return ReadXml (new XmlTextReader (stream));
794 public XmlReadMode ReadXml (string str)
796 XmlTextReader reader = new XmlTextReader (str);
798 return ReadXml (reader);
805 public XmlReadMode ReadXml (TextReader reader)
807 return ReadXml (new XmlTextReader (reader));
810 public XmlReadMode ReadXml (XmlReader r)
812 XmlDataLoader Loader = new XmlDataLoader (this);
813 // FIXME: somekinda exception?
815 return XmlReadMode.Auto; // FIXME
817 // Check if the curent element is the process instruction (PI).
818 // if it is move to next element.
819 if (r.LocalName == "xml")
822 // The document can be diffgram if :
823 // 1. The first element is diffgram.
824 if (r.LocalName == "diffgram") {
825 return ReadXml (r, XmlReadMode.DiffGram);
828 bool schemaRead = false;
829 if (r.LocalName == "schema") {
835 // If we read the schema the next element can be a diffgram
836 // that is what happen in web services soap message.
837 if (schemaRead && r.LocalName == "diffgram") {
838 return ReadXml (r, XmlReadMode.DiffGram);
841 // Get the DataSet name.
842 // if this xml is not diffgram then the first element will be the
844 string dataSetName = XmlConvert.DecodeName (r.LocalName);
845 DataSetName = dataSetName;
847 r.ReadStartElement ();
851 // After reading the dataset name there can be three scenarios:
852 // 1. The next part will be the schema of the dataset.
853 // 2. The next part will be the data of the dataset using diffgram.
854 // 3. The next part will be the data of tha dataset without diffgram.
855 // Check if the current element is the schema
856 if (r.LocalName == "schema") {
862 // check if the data was written in a diffgram mode.
863 if (r.LocalName == "diffgram") {
864 return ReadXml (r, XmlReadMode.DiffGram);
867 // If the schema has been read we should read the rest data of the dataset
868 // with ignoreschema mode.
870 ReadXml (r, XmlReadMode.IgnoreSchema, false);
871 return XmlReadMode.ReadSchema;
874 // Read the data of the dataset with inferschema.
875 return ReadXml (r, XmlReadMode.InferSchema, false);
879 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
881 return ReadXml (new XmlTextReader (stream), mode);
884 public XmlReadMode ReadXml (string str, XmlReadMode mode)
886 XmlTextReader reader = new XmlTextReader (str);
888 return ReadXml (reader, mode);
895 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
897 return ReadXml (new XmlTextReader (reader), mode);
901 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
903 // we have to initiate the reader.
904 if (reader.ReadState == ReadState.Initial)
907 // Check if the curent element is the process instruction (PI).
908 // if it is move to next element.
909 if (reader.LocalName == "xml")
910 reader.MoveToContent();
912 XmlReadMode Result = XmlReadMode.Auto;
914 if (mode == XmlReadMode.DiffGram) {
915 if (reader.LocalName != "diffgram"){
916 reader.MoveToContent ();
917 reader.ReadStartElement (); // <DataSet>
919 reader.MoveToContent ();
920 if (reader.LocalName == "schema")
921 ReadXmlSchema (reader);
923 reader.MoveToContent ();
925 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
926 DiffLoader.Load (reader);
927 Result = XmlReadMode.DiffGram;
930 Result = ReadXml(reader, mode, true);
935 private XmlReadMode ReadXml (XmlReader r, XmlReadMode mode, bool readDataSet) {
938 string dataSetName = XmlConvert.DecodeName (r.LocalName);
939 DataSetName = dataSetName;
940 // get the Namespace of the DataSet.
941 string tmp = r.GetAttribute("xmlns");
945 r.ReadStartElement ();
949 XmlDataLoader Loader = new XmlDataLoader (this);
950 return Loader.LoadData (r, mode);
953 #endregion // Public Methods
955 #region Public Events
957 [DataCategory ("Action")]
958 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
959 public event MergeFailedEventHandler MergeFailed;
961 #endregion // Public Events
969 #endregion Destructors
971 #region IListSource methods
972 IList IListSource.GetList ()
974 return DefaultViewManager;
977 bool IListSource.ContainsListCollection {
982 #endregion IListSource methods
984 #region ISupportInitialize methods
985 public void BeginInit ()
989 public void EndInit ()
994 #region ISerializable
995 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
997 throw new NotImplementedException ();
1001 #region Protected Methods
1002 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
1004 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
1005 if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s)));
1009 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
1014 protected virtual void ReadXmlSerializable (XmlReader reader)
1016 ReadXml (reader, XmlReadMode.DiffGram); // FIXME
1019 void IXmlSerializable.ReadXml (XmlReader reader)
1022 ReadXmlSerializable(reader);
1024 // the XmlSerializationReader does this lines!!!
1025 //reader.MoveToContent ();
1026 //reader.ReadEndElement (); // </DataSet>
1029 void IXmlSerializable.WriteXml (XmlWriter writer)
1031 DoWriteXmlSchema (writer);
1032 WriteXml (writer, XmlWriteMode.DiffGram, true);
1035 protected virtual bool ShouldSerializeRelations ()
1040 protected virtual bool ShouldSerializeTables ()
1046 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
1051 protected virtual void OnRemoveRelation (DataRelation relation)
1056 protected virtual void OnRemoveTable (DataTable table)
1060 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
1062 if (MergeFailed != null)
1063 MergeFailed (this, e);
1067 protected internal void RaisePropertyChanging (string name)
1072 #region Private Xml Serialisation
1074 private string WriteObjectXml (object o)
1076 switch (Type.GetTypeCode (o.GetType ())) {
1077 case TypeCode.Boolean:
1078 return XmlConvert.ToString ((Boolean) o);
1080 return XmlConvert.ToString ((Byte) o);
1082 return XmlConvert.ToString ((Char) o);
1083 case TypeCode.DateTime:
1084 return XmlConvert.ToString ((DateTime) o);
1085 case TypeCode.Decimal:
1086 return XmlConvert.ToString ((Decimal) o);
1087 case TypeCode.Double:
1088 return XmlConvert.ToString ((Double) o);
1089 case TypeCode.Int16:
1090 return XmlConvert.ToString ((Int16) o);
1091 case TypeCode.Int32:
1092 return XmlConvert.ToString ((Int32) o);
1093 case TypeCode.Int64:
1094 return XmlConvert.ToString ((Int64) o);
1095 case TypeCode.SByte:
1096 return XmlConvert.ToString ((SByte) o);
1097 case TypeCode.Single:
1098 return XmlConvert.ToString ((Single) o);
1099 case TypeCode.UInt16:
1100 return XmlConvert.ToString ((UInt16) o);
1101 case TypeCode.UInt32:
1102 return XmlConvert.ToString ((UInt32) o);
1103 case TypeCode.UInt64:
1104 return XmlConvert.ToString ((UInt64) o);
1106 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
1107 if (o is Guid) return XmlConvert.ToString ((Guid) o);
1108 if (o is byte[]) return Convert.ToBase64String ((byte[])o);
1109 return o.ToString ();
1112 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
1114 //Write out each table in order, providing it is not
1115 //part of another table structure via a nested parent relationship
1116 foreach (DataTable table in tableCollection) {
1117 bool isTopLevel = true;
1118 foreach (DataRelation rel in table.ParentRelations) {
1126 WriteTable ( writer, table, mode, version);
1131 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
1133 DataRow[] rows = new DataRow [table.Rows.Count];
1134 table.Rows.CopyTo (rows, 0);
1135 WriteTable (writer, rows, mode, version);
1138 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1140 //The columns can be attributes, hidden, elements, or simple content
1141 //There can be 0-1 simple content cols or 0-* elements
1142 System.Collections.ArrayList atts;
1143 System.Collections.ArrayList elements;
1144 DataColumn simple = null;
1146 if (rows.Length == 0) return;
1147 DataTable table = rows[0].Table;
1148 SplitColumns (table, out atts, out elements, out simple);
1149 //sort out the namespacing
1150 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1152 foreach (DataRow row in rows) {
1153 if (!row.HasVersion(version) ||
1154 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
1155 && version == DataRowVersion.Original))
1158 // First check are all the rows null. If they are we just write empty element
1159 bool AllNulls = true;
1160 foreach (DataColumn dc in table.Columns) {
1162 if (row [dc.ColumnName, version] != DBNull.Value) {
1168 // If all of the columns were null, we have to write empty element
1170 writer.WriteElementString (table.TableName, "");
1174 WriteTableElement (writer, mode, table, row, version);
1176 foreach (DataColumn col in atts) {
1177 WriteColumnAsAttribute (writer, mode, col, row, version);
1180 if (simple != null) {
1181 writer.WriteString (WriteObjectXml (row[simple, version]));
1184 foreach (DataColumn col in elements) {
1185 WriteColumnAsElement (writer, mode, nspc, col, row, version);
1189 foreach (DataRelation relation in table.ChildRelations) {
1190 if (relation.Nested) {
1191 WriteTable (writer, row.GetChildRows (relation), mode, version);
1195 writer.WriteEndElement ();
1200 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
1202 string colnspc = nspc;
1203 object rowObject = row [col, version];
1205 if (rowObject == null || rowObject == DBNull.Value)
1208 if (col.Namespace != null) {
1209 colnspc = col.Namespace;
1212 //TODO check if I can get away with write element string
1213 WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName);
1214 writer.WriteString (WriteObjectXml (rowObject));
1215 writer.WriteEndElement ();
1218 private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1220 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
1223 private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
1225 //sort out the namespacing
1226 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1228 WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
1230 if (mode == XmlWriteMode.DiffGram) {
1231 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
1232 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", row.XmlRowID.ToString());
1233 string modeName = null;
1234 if (row.RowState == DataRowState.Modified)
1235 modeName = "modified";
1236 else if (row.RowState == DataRowState.Added)
1237 modeName = "inserted";
1239 if (version != DataRowVersion.Original && modeName != null)
1240 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
1244 private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
1246 if (nspc == null || nspc == "") {
1247 writer.WriteStartElement (name);
1249 else if (prefix != null) {
1250 writer.WriteStartElement (prefix, name, nspc);
1253 writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
1257 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1260 case XmlWriteMode.WriteSchema:
1261 writer.WriteAttributeString (prefix, name, nspc);
1263 case XmlWriteMode.DiffGram:
1264 writer.WriteAttributeString (prefix, name, nspc,stringValue);
1267 writer.WriteAttributeString (name, stringValue);
1272 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
1274 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
1276 if (mode == XmlWriteMode.DiffGram) {
1277 SetTableRowsID (table);
1278 WriteDiffGramElement (writer);
1281 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
1283 WriteTable (writer, table, mode, DataRowVersion.Default);
1285 if (mode == XmlWriteMode.DiffGram) {
1286 writer.WriteEndElement (); //DataSet name
1287 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
1289 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
1290 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
1291 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
1292 writer.WriteEndElement ();
1295 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
1298 XmlSchema IXmlSerializable.GetSchema ()
1300 return BuildSchema ();
1303 XmlSchema BuildSchema ()
1305 return BuildSchema (Tables, Relations);
1308 internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
1310 string constraintPrefix = "";
1311 XmlSchema schema = new XmlSchema ();
1313 schema.Namespaces.Add("xs", XmlSchema.Namespace);
1314 schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1316 if (Namespace != "" && Namespace != null) {
1317 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1318 schema.ElementFormDefault = XmlSchemaForm.Qualified;
1319 schema.TargetNamespace = Namespace;
1320 schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
1321 constraintPrefix = XmlConstants.TnsPrefix + ":";
1324 // set the schema id
1325 schema.Id = DataSetName;
1326 XmlDocument doc = new XmlDocument ();
1327 XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
1328 xmlnsAttr.Value = Namespace;
1330 schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
1332 XmlSchemaElement elem = new XmlSchemaElement ();
1333 elem.Name = XmlConvert.EncodeName (DataSetName);
1335 XmlAttribute[] atts = new XmlAttribute [2];
1336 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1337 atts[0].Value = "true";
1339 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1340 atts[1].Value = locale.Name;
1341 elem.UnhandledAttributes = atts;
1343 schema.Items.Add (elem);
1345 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1346 elem.SchemaType = complex;
1348 XmlSchemaChoice choice = new XmlSchemaChoice ();
1349 complex.Particle = choice;
1350 choice.MaxOccursString = XmlConstants.Unbounded;
1352 //Write out schema for each table in order
1353 foreach (DataTable table in tables) {
1354 bool isTopLevel = true;
1355 foreach (DataRelation rel in table.ParentRelations) {
1363 choice.Items.Add (GetTableSchema (doc, table));
1367 AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
1371 // Add all constraints in all tables to the schema.
1372 private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
1374 // first add all unique constraints.
1375 Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
1376 // Add all foriegn key constraints.
1377 AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
1380 // Add unique constaraints to the schema.
1381 // return hashtable with the names of all XmlSchemaUnique elements we created.
1382 private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
1384 XmlDocument doc = new XmlDocument();
1385 Hashtable uniqueNames = new Hashtable();
1386 foreach (DataTable table in tables) {
1388 foreach (Constraint constaint in table.Constraints) {
1390 if (constaint is UniqueConstraint) {
1391 ArrayList attrs = new ArrayList ();
1392 XmlAttribute attrib;
1393 UniqueConstraint uqConst = (UniqueConstraint)constaint;
1394 XmlSchemaUnique uniq = new XmlSchemaUnique ();
1396 // if column of the constraint is hidden do not write the constraint.
1397 bool isHidden = false;
1398 foreach (DataColumn column in uqConst.Columns) {
1399 if (column.ColumnMapping == MappingType.Hidden) {
1408 // if constaraint name do not exist in the hashtable we can use it.
1409 if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
1410 uniq.Name = uqConst.ConstraintName;
1412 // generate new constraint name for the XmlSchemaUnique element.
1414 uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
1415 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1416 attrib.Value = uqConst.ConstraintName;
1419 if (uqConst.IsPrimaryKey) {
1420 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
1421 attrib.Value = "true";
1425 uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1427 uniq.Selector = new XmlSchemaXPath();
1428 uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
1429 XmlSchemaXPath field;
1430 foreach (DataColumn column in uqConst.Columns) {
1431 field = new XmlSchemaXPath();
1432 field.XPath = constraintPrefix+column.ColumnName;
1433 uniq.Fields.Add(field);
1436 elem.Constraints.Add (uniq);
1437 uniqueNames.Add (uniq.Name, null);
1444 // Add the foriegn keys to the schema.
1445 private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
1447 if (relations == null) return;
1449 XmlDocument doc = new XmlDocument();
1450 foreach (DataRelation rel in relations) {
1452 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
1455 ArrayList attrs = new ArrayList ();
1456 XmlAttribute attrib;
1457 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1458 keyRef.Name = rel.RelationName;
1459 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1460 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1462 string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
1463 // first try to find the concatenated name. If we didn't find it - use constraint name.
1464 if (uniqueNames.ContainsKey (concatName)) {
1465 keyRef.Refer = new XmlQualifiedName(concatName);
1468 keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
1472 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1473 attrib.Value = "true";
1477 keyRef.Selector = new XmlSchemaXPath();
1478 keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
1479 XmlSchemaXPath field;
1480 foreach (DataColumn column in rel.ChildColumns) {
1481 field = new XmlSchemaXPath();
1482 field.XPath = constraintPrefix+column.ColumnName;
1483 keyRef.Fields.Add(field);
1485 keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1486 elem.Constraints.Add (keyRef);
1490 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1496 SplitColumns (table, out atts, out elements, out simple);
1498 XmlSchemaElement elem = new XmlSchemaElement ();
1499 elem.Name = table.TableName;
1501 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1502 elem.SchemaType = complex;
1504 //TODO - what about the simple content?
1505 if (simple != null) {
1506 // add simpleContent
1507 XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
1508 complex.ContentModel = simpleContent;
1510 // add column name attribute
1511 XmlAttribute[] xlmAttrs = new XmlAttribute [2];
1512 xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
1513 xlmAttrs[0].Value = simple.ColumnName;
1515 // add ordinal attribute
1516 xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
1517 xlmAttrs[1].Value = simple.Ordinal.ToString();
1518 simpleContent.UnhandledAttributes = xlmAttrs;
1522 XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
1523 simpleContent.Content = extension;
1524 extension.BaseTypeName = MapType (simple.DataType);
1528 //A sequence of element types or a simple content node
1530 XmlSchemaSequence seq = new XmlSchemaSequence ();
1531 complex.Particle = seq;
1533 foreach (DataColumn col in elements) {
1535 // Add element for the column.
1536 XmlSchemaElement colElem = new XmlSchemaElement ();
1537 ArrayList xattrs = new ArrayList();
1539 colElem.Name = col.ColumnName;
1541 if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
1542 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1543 xattr.Value = col.Caption;
1547 if (col.AutoIncrement == true) {
1548 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
1549 xattr.Value = "true";
1553 if (col.AutoIncrementSeed != 0) {
1554 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
1555 xattr.Value = col.AutoIncrementSeed.ToString();
1559 if (col.DefaultValue.ToString () != String.Empty)
1560 colElem.DefaultValue = col.DefaultValue.ToString ();
1562 if (col.MaxLength < 0)
1563 colElem.SchemaTypeName = MapType (col.DataType);
1565 if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string)
1566 && col.DataType != typeof (char)) {
1567 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
1568 xattr.Value = col.DataType.ToString();
1572 if (col.AllowDBNull) {
1573 colElem.MinOccurs = 0;
1576 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
1577 // XmlConstants.Ordinal,
1578 // XmlConstants.MsdataNamespace,
1579 // col.Ordinal.ToString ());
1581 // Write SimpleType if column have MaxLength
1582 if (col.MaxLength > -1) {
1583 colElem.SchemaType = GetTableSimpleType (doc, col);
1586 colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
1587 seq.Items.Add (colElem);
1590 foreach (DataRelation rel in table.ChildRelations) {
1592 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1597 //Then a list of attributes
1598 foreach (DataColumn col in atts) {
1599 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1600 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1601 att.Name = col.ColumnName;
1602 att.Form = XmlSchemaForm.Unqualified;
1603 att.SchemaTypeName = MapType (col.DataType);
1604 complex.Attributes.Add (att);
1610 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1613 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1616 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1617 restriction.BaseTypeName = MapType (col.DataType);
1620 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1621 max.Value = XmlConvert.ToString (col.MaxLength);
1622 restriction.Facets.Add (max);
1624 simple.Content = restriction;
1628 private void DoWriteXmlSchema (XmlWriter writer)
1630 BuildSchema ().Write (writer);
1634 /// Helper function to split columns into attributes elements and simple
1637 private void SplitColumns (DataTable table,
1639 out ArrayList elements,
1640 out DataColumn simple)
1642 //The columns can be attributes, hidden, elements, or simple content
1643 //There can be 0-1 simple content cols or 0-* elements
1644 atts = new System.Collections.ArrayList ();
1645 elements = new System.Collections.ArrayList ();
1648 //Sort out the columns
1649 foreach (DataColumn col in table.Columns) {
1650 switch (col.ColumnMapping) {
1651 case MappingType.Attribute:
1654 case MappingType.Element:
1657 case MappingType.SimpleContent:
1658 if (simple != null) {
1659 throw new System.InvalidOperationException ("There may only be one simple content element");
1664 //ignore Hidden elements
1670 private void WriteDiffGramElement(XmlWriter writer)
1672 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
1673 WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1676 private void SetRowsID()
1678 foreach (DataTable Table in Tables)
1679 SetTableRowsID (Table);
1682 private void SetTableRowsID (DataTable Table)
1685 foreach (DataRow Row in Table.Rows) {
1686 Row.XmlRowID = dataRowID;
1692 private XmlQualifiedName MapType (Type type)
1694 switch (Type.GetTypeCode (type)) {
1695 case TypeCode.String: return XmlConstants.QnString;
1696 case TypeCode.Int16: return XmlConstants.QnShort;
1697 case TypeCode.Int32: return XmlConstants.QnInt;
1698 case TypeCode.Int64: return XmlConstants.QnLong;
1699 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1700 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1701 //case TypeCode.Char: return XmlConstants.QnChar;
1702 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1703 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1704 case TypeCode.Double: return XmlConstants.QnDouble;
1705 case TypeCode.SByte: return XmlConstants.QnSbyte;
1706 case TypeCode.Single: return XmlConstants.QnFloat;
1707 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1708 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1709 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1712 if (typeof (TimeSpan) == type)
1713 return XmlConstants.QnDuration;
1714 else if (typeof (System.Uri) == type)
1715 return XmlConstants.QnUri;
1716 else if (typeof (byte[]) == type)
1717 return XmlConstants.QnBase64Binary;
1718 else if (typeof (XmlQualifiedName) == type)
1719 return XmlConstants.QnXmlQualifiedName;
1721 return XmlConstants.QnString;
1724 #endregion //Private Xml Serialisation