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>
11 // Atsushi Enomoto <atsushi@ximian.com>
13 // (C) Ximian, Inc. 2002
14 // Copyright (C) Tim Coleman, 2002, 2003
18 using System.Collections;
19 using System.ComponentModel;
20 using System.Globalization;
21 using System.Threading;
23 using System.Runtime.Serialization;
25 using System.Xml.Schema;
26 using System.Xml.Serialization;
27 using System.Data.Common;
29 namespace System.Data {
32 [DefaultProperty ("DataSetName")]
34 public class DataSet : MarshalByValueComponent, IListSource,
35 ISupportInitialize, ISerializable, IXmlSerializable
37 private string dataSetName;
38 private string _namespace = "";
39 private string prefix;
40 private bool caseSensitive;
41 private bool enforceConstraints = true;
42 private DataTableCollection tableCollection;
43 private DataRelationCollection relationCollection;
44 private PropertyCollection properties;
45 private DataViewManager defaultView;
46 private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
47 internal XmlDataDocument _xmlDataDocument = null;
51 public DataSet () : this ("NewDataSet")
55 public DataSet (string name)
58 tableCollection = new DataTableCollection (this);
59 relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
60 properties = new PropertyCollection ();
61 this.prefix = String.Empty;
63 this.Locale = CultureInfo.CurrentCulture;
66 protected DataSet (SerializationInfo info, StreamingContext context) : this ()
68 GetSerializationData (info, context);
71 #endregion // Constructors
73 #region Public Properties
75 [DataCategory ("Data")]
76 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
77 [DefaultValue (false)]
78 public bool CaseSensitive {
83 caseSensitive = value;
85 foreach (DataTable table in Tables) {
86 foreach (Constraint c in table.Constraints)
87 c.AssertConstraint ();
93 [DataCategory ("Data")]
94 [DataSysDescription ("The name of this DataSet.")]
96 public string DataSetName {
97 get { return dataSetName; }
98 set { dataSetName = value; }
101 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
103 public DataViewManager DefaultViewManager {
105 if (defaultView == null)
106 defaultView = new DataViewManager (this);
111 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
112 [DefaultValue (true)]
113 public bool EnforceConstraints {
114 get { return enforceConstraints; }
116 if (value != enforceConstraints) {
117 enforceConstraints = value;
119 foreach (DataTable table in Tables) {
120 // first assert all unique constraints
121 foreach (UniqueConstraint uc in table.Constraints.UniqueConstraints)
122 uc.AssertConstraint ();
123 // then assert all foreign keys
124 foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
125 fk.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 {
232 get { return _namespace; }
234 //TODO - trigger an event if this happens?
236 value = String.Empty;
237 if (value != this._namespace)
238 RaisePropertyChanging ("Namespace");
243 [DataCategory ("Data")]
244 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
246 public string Prefix {
247 get { return prefix; }
250 value = String.Empty;
251 // Prefix cannot contain any special characters other than '_' and ':'
252 for (int i = 0; i < value.Length; i++) {
253 if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
254 throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
259 value = string.Empty;
261 if (value != this.prefix)
262 RaisePropertyChanging ("Prefix");
267 [DataCategory ("Data")]
268 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
269 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
270 public DataRelationCollection Relations {
272 return relationCollection;
277 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
278 public override ISite Site {
281 throw new NotImplementedException ();
286 throw new NotImplementedException ();
290 [DataCategory ("Data")]
291 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
292 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
293 public DataTableCollection Tables {
294 get { return tableCollection; }
297 #endregion // Public Properties
299 #region Public Methods
302 public void AcceptChanges ()
304 foreach (DataTable tempTable in tableCollection)
305 tempTable.AcceptChanges ();
310 if (_xmlDataDocument != null)
311 throw new NotSupportedException ("Clear function on dataset and datatable is not supported on XmlDataDocument.");
312 for (int t = 0; t < tableCollection.Count; t++) {
313 tableCollection[t].Clear ();
317 public virtual DataSet Clone ()
319 DataSet Copy = new DataSet ();
320 CopyProperties (Copy);
322 foreach (DataTable Table in Tables) {
323 Copy.Tables.Add (Table.Clone ());
326 //Copy Relationships between tables after existance of tables
327 //and setting properties correctly
328 CopyRelations (Copy);
333 // Copies both the structure and data for this DataSet.
334 public DataSet Copy ()
336 DataSet Copy = new DataSet ();
337 CopyProperties (Copy);
339 // Copy DatSet's tables
340 foreach (DataTable Table in Tables)
341 Copy.Tables.Add (Table.Copy ());
343 //Copy Relationships between tables after existance of tables
344 //and setting properties correctly
345 CopyRelations (Copy);
350 private void CopyProperties (DataSet Copy)
352 Copy.CaseSensitive = CaseSensitive;
353 //Copy.Container = Container
354 Copy.DataSetName = DataSetName;
355 //Copy.DefaultViewManager
357 Copy.EnforceConstraints = EnforceConstraints;
358 if(ExtendedProperties.Count > 0) {
359 // Cannot copy extended properties directly as the property does not have a set accessor
360 Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
361 ExtendedProperties.Keys.CopyTo (tgtArray, 0);
362 for (int i=0; i < ExtendedProperties.Count; i++)
363 Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
365 Copy.Locale = Locale;
366 Copy.Namespace = Namespace;
367 Copy.Prefix = Prefix;
368 //Copy.Site = Site; // FIXME : Not sure of this.
373 private void CopyRelations (DataSet Copy)
376 //Creation of the relation contains some of the properties, and the constructor
377 //demands these values. instead changing the DataRelation constructor and behaviour the
378 //parameters are pre-configured and sent to the most general constructor
380 foreach (DataRelation MyRelation in this.Relations) {
381 string pTable = MyRelation.ParentTable.TableName;
382 string cTable = MyRelation.ChildTable.TableName;
383 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];
384 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
387 foreach (DataColumn DC in MyRelation.ParentColumns) {
388 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
394 foreach (DataColumn DC in MyRelation.ChildColumns) {
395 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
399 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
400 //cRel.ChildColumns = MyRelation.ChildColumns;
401 //cRel.ChildTable = MyRelation.ChildTable;
402 //cRel.ExtendedProperties = cRel.ExtendedProperties;
403 //cRel.Nested = MyRelation.Nested;
404 //cRel.ParentColumns = MyRelation.ParentColumns;
405 //cRel.ParentTable = MyRelation.ParentTable;
407 Copy.Relations.Add (cRel);
414 public DataSet GetChanges ()
416 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
420 public DataSet GetChanges (DataRowState rowStates)
422 if (!HasChanges (rowStates))
425 DataSet copySet = Clone ();
426 Hashtable addedRows = new Hashtable ();
428 IEnumerator tableEnumerator = Tables.GetEnumerator ();
431 while (tableEnumerator.MoveNext ()) {
432 origTable = (DataTable)tableEnumerator.Current;
433 copyTable = copySet.Tables[origTable.TableName];
435 // Look for relations that have this table as child
436 IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
438 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
439 while (rowEnumerator.MoveNext ()) {
440 DataRow row = (DataRow)rowEnumerator.Current;
442 if (row.IsRowChanged (rowStates))
443 AddChangedRow (addedRows, copySet, copyTable, relations, row);
449 void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
451 if (addedRows.ContainsKey (row)) return;
454 while (relations.MoveNext ()) {
455 DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
456 if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
457 DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
458 AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
461 DataRow newRow = copyTable.NewRow ();
462 copyTable.Rows.Add (newRow);
463 row.CopyValuesToRow (newRow);
464 newRow.XmlRowID = row.XmlRowID;
465 addedRows.Add (row,row);
470 public DataTableReader GetDataReader (DataTable[] dataTables)
472 throw new NotImplementedException ();
476 public DataTableReader GetDataReader ()
478 throw new NotImplementedException ();
482 public string GetXml ()
484 StringWriter Writer = new StringWriter ();
485 WriteXml (Writer, XmlWriteMode.IgnoreSchema);
486 return Writer.ToString ();
489 public string GetXmlSchema ()
491 StringWriter Writer = new StringWriter ();
492 WriteXmlSchema (Writer);
493 return Writer.ToString ();
497 public bool HasChanges ()
499 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
503 public bool HasChanges (DataRowState rowState)
505 if (((int)rowState & 0xffffffe0) != 0)
506 throw new ArgumentOutOfRangeException ("rowState");
508 DataTableCollection tableCollection = Tables;
510 DataRowCollection rowCollection;
513 for (int i = 0; i < tableCollection.Count; i++) {
514 table = tableCollection[i];
515 rowCollection = table.Rows;
516 for (int j = 0; j < rowCollection.Count; j++) {
517 row = rowCollection[j];
518 if ((row.RowState & rowState) != 0)
526 [MonoTODO ("Consider ignored namespace array")]
527 public void InferXmlSchema (XmlReader reader, string[] nsArray)
532 XmlDataLoader Loader = new XmlDataLoader (this);
533 Loader.LoadData (reader, XmlReadMode.InferSchema);
536 public void InferXmlSchema (Stream stream, string[] nsArray)
538 InferXmlSchema (new XmlTextReader (stream), nsArray);
541 public void InferXmlSchema (TextReader reader, string[] nsArray)
543 InferXmlSchema (new XmlTextReader (reader), nsArray);
546 public void InferXmlSchema (string fileName, string[] nsArray)
548 XmlTextReader reader = new XmlTextReader (fileName);
550 InferXmlSchema (reader, nsArray);
558 public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
560 throw new NotImplementedException ();
564 public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
566 throw new NotImplementedException ();
570 public virtual void RejectChanges ()
573 bool oldEnforceConstraints = this.EnforceConstraints;
574 this.EnforceConstraints = false;
576 for (i = 0; i < this.Tables.Count;i++)
577 this.Tables[i].RejectChanges ();
579 this.EnforceConstraints = oldEnforceConstraints;
582 public virtual void Reset ()
584 IEnumerator constraintEnumerator;
586 // first we remove all ForeignKeyConstraints (if we will not do that
587 // we will get an exception when clearing the tables).
588 for (int i = 0; i < Tables.Count; i++) {
589 ConstraintCollection cc = Tables[i].Constraints;
590 for (int j = 0; j < cc.Count; j++) {
591 if (cc[j] is ForeignKeyConstraint)
601 public void WriteXml (Stream stream)
603 XmlTextWriter writer = new XmlTextWriter (stream, null);
604 writer.Formatting = Formatting.Indented;
609 /// Writes the current data for the DataSet to the specified file.
611 /// <param name="filename">Fully qualified filename to write to</param>
612 public void WriteXml (string fileName)
614 XmlTextWriter writer = new XmlTextWriter (fileName, null);
615 writer.Formatting = Formatting.Indented;
616 writer.WriteStartDocument (true);
621 writer.WriteEndDocument ();
626 public void WriteXml (TextWriter writer)
628 XmlTextWriter xwriter = new XmlTextWriter (writer);
629 xwriter.Formatting = Formatting.Indented;
633 public void WriteXml (XmlWriter writer)
635 WriteXml (writer, XmlWriteMode.IgnoreSchema);
638 public void WriteXml (string filename, XmlWriteMode mode)
640 XmlTextWriter writer = new XmlTextWriter (filename, null);
641 writer.Formatting = Formatting.Indented;
642 writer.WriteStartDocument (true);
645 WriteXml (writer, mode);
648 writer.WriteEndDocument ();
653 public void WriteXml (Stream stream, XmlWriteMode mode)
655 XmlTextWriter writer = new XmlTextWriter (stream, null);
656 writer.Formatting = Formatting.Indented;
657 WriteXml (writer, mode);
660 public void WriteXml (TextWriter writer, XmlWriteMode mode)
662 XmlTextWriter xwriter = new XmlTextWriter (writer);
663 xwriter.Formatting = Formatting.Indented;
664 WriteXml (xwriter, mode);
667 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
669 if (mode == XmlWriteMode.DiffGram) {
671 WriteDiffGramElement(writer);
674 // It should not write when there is no content to be written
675 bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
\r
676 for (int n=0; n<tableCollection.Count && !shouldOutputContent; n++)
\r
677 shouldOutputContent = tableCollection [n].Rows.Count > 0;
\r
679 if (shouldOutputContent) {
680 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
682 if (mode == XmlWriteMode.WriteSchema)
683 DoWriteXmlSchema (writer);
685 WriteTables (writer, mode, Tables, DataRowVersion.Default);
686 writer.WriteEndElement ();
689 if (mode == XmlWriteMode.DiffGram) {
690 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
692 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
693 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
694 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
695 writer.WriteEndElement ();
699 if (mode == XmlWriteMode.DiffGram)
700 writer.WriteEndElement (); // diffgr:diffgram
703 public void WriteXmlSchema (Stream stream)
705 XmlTextWriter writer = new XmlTextWriter (stream, null );
706 writer.Formatting = Formatting.Indented;
707 WriteXmlSchema (writer);
710 public void WriteXmlSchema (string fileName)
712 XmlTextWriter writer = new XmlTextWriter (fileName, null);
714 writer.Formatting = Formatting.Indented;
715 writer.WriteStartDocument (true);
716 WriteXmlSchema (writer);
718 writer.WriteEndDocument ();
723 public void WriteXmlSchema (TextWriter writer)
725 XmlTextWriter xwriter = new XmlTextWriter (writer);
727 xwriter.Formatting = Formatting.Indented;
728 // xwriter.WriteStartDocument ();
729 WriteXmlSchema (xwriter);
731 // xwriter.WriteEndDocument ();
736 public void WriteXmlSchema (XmlWriter writer)
738 //Create a skeleton doc and then write the schema
739 //proper which is common to the WriteXml method in schema mode
740 DoWriteXmlSchema (writer);
743 public void ReadXmlSchema (Stream stream)
745 XmlReader reader = new XmlTextReader (stream, null);
746 ReadXmlSchema (reader);
749 public void ReadXmlSchema (string str)
751 XmlReader reader = new XmlTextReader (str);
753 ReadXmlSchema (reader);
760 public void ReadXmlSchema (TextReader treader)
762 XmlReader reader = new XmlTextReader (treader);
763 ReadXmlSchema (reader);
766 public void ReadXmlSchema (XmlReader reader)
769 new XmlSchemaDataImporter (this, reader);
771 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
772 SchemaMapper.Read (reader);
776 public XmlReadMode ReadXml (Stream stream)
778 return ReadXml (new XmlTextReader (stream));
781 public XmlReadMode ReadXml (string str)
783 XmlTextReader reader = new XmlTextReader (str);
785 return ReadXml (reader);
792 public XmlReadMode ReadXml (TextReader reader)
794 return ReadXml (new XmlTextReader (reader));
797 public XmlReadMode ReadXml (XmlReader r)
799 return ReadXml (r, XmlReadMode.Auto);
802 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
804 return ReadXml (new XmlTextReader (stream), mode);
807 public XmlReadMode ReadXml (string str, XmlReadMode mode)
809 XmlTextReader reader = new XmlTextReader (str);
811 return ReadXml (reader, mode);
818 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
820 return ReadXml (new XmlTextReader (reader), mode);
824 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
826 switch (reader.ReadState) {
827 case ReadState.EndOfFile:
828 case ReadState.Error:
829 case ReadState.Closed:
832 // Skip XML declaration and prolog
833 reader.MoveToContent();
837 XmlReadMode Result = mode;
839 // If diffgram, then read the first element as diffgram
840 if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
842 case XmlReadMode.Auto:
843 case XmlReadMode.DiffGram:
844 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
845 DiffLoader.Load (reader);
846 // (and leave rest of the reader as is)
847 return XmlReadMode.DiffGram;
848 case XmlReadMode.Fragment:
850 // (and continue to read)
854 // (and leave rest of the reader as is)
858 // If schema, then read the first element as schema
859 if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
861 case XmlReadMode.IgnoreSchema:
862 case XmlReadMode.InferSchema:
864 // (and break up read)
866 case XmlReadMode.Fragment:
867 ReadXmlSchema (reader);
868 // (and continue to read)
870 case XmlReadMode.Auto:
871 if (Tables.Count == 0) {
872 ReadXmlSchema (reader);
873 return XmlReadMode.ReadSchema;
875 // otherwise just ignore and return IgnoreSchema
877 return XmlReadMode.IgnoreSchema;
880 ReadXmlSchema (reader);
881 // (and leave rest of the reader as is)
882 return mode; // When DiffGram, return DiffGram
885 // Otherwise, read as dataset... but only when required.
887 case XmlReadMode.Auto:
888 case XmlReadMode.InferSchema:
889 case XmlReadMode.IgnoreSchema:
890 case XmlReadMode.Fragment:
896 XmlDataLoader Loader = new XmlDataLoader (this);
897 return Loader.LoadData (reader, mode);
899 #endregion // Public Methods
901 #region Public Events
903 [DataCategory ("Action")]
904 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
905 public event MergeFailedEventHandler MergeFailed;
907 #endregion // Public Events
915 #endregion Destructors
917 #region IListSource methods
918 IList IListSource.GetList ()
920 return DefaultViewManager;
923 bool IListSource.ContainsListCollection {
928 #endregion IListSource methods
930 #region ISupportInitialize methods
931 public void BeginInit ()
935 public void EndInit ()
940 #region ISerializable
941 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
943 StringWriter sw = new StringWriter ();
944 XmlTextWriter writer = new XmlTextWriter (sw);
945 DoWriteXmlSchema (writer);
947 si.AddValue ("XmlSchema", sw.ToString ());
949 sw = new StringWriter ();
950 writer = new XmlTextWriter (sw);
951 WriteXml (writer, XmlWriteMode.DiffGram);
953 si.AddValue ("XmlDiffGram", sw.ToString ());
957 #region Protected Methods
958 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
960 string s = info.GetValue ("XmlSchema", typeof (String)) as String;
961 XmlTextReader reader = new XmlTextReader (new StringReader (s));
962 ReadXmlSchema (reader);
965 s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
966 reader = new XmlTextReader (new StringReader (s));
967 ReadXml (reader, XmlReadMode.DiffGram);
972 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
977 protected virtual void ReadXmlSerializable (XmlReader reader)
979 reader.MoveToContent ();
980 reader.ReadStartElement ();
981 reader.MoveToContent ();
982 ReadXmlSchema (reader);
983 reader.MoveToContent ();
984 ReadXml (reader, XmlReadMode.DiffGram);
985 reader.MoveToContent ();
986 reader.ReadEndElement ();
989 void IXmlSerializable.ReadXml (XmlReader reader)
991 ReadXmlSerializable(reader);
994 void IXmlSerializable.WriteXml (XmlWriter writer)
996 DoWriteXmlSchema (writer);
997 WriteXml (writer, XmlWriteMode.DiffGram);
1000 protected virtual bool ShouldSerializeRelations ()
1005 protected virtual bool ShouldSerializeTables ()
1011 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
1016 protected virtual void OnRemoveRelation (DataRelation relation)
1021 protected virtual void OnRemoveTable (DataTable table)
1025 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
1027 if (MergeFailed != null)
1028 MergeFailed (this, e);
1032 protected internal void RaisePropertyChanging (string name)
1037 #region Private Xml Serialisation
1039 private string WriteObjectXml (object o)
1041 switch (Type.GetTypeCode (o.GetType ())) {
1042 case TypeCode.Boolean:
1043 return XmlConvert.ToString ((Boolean) o);
1045 return XmlConvert.ToString ((Byte) o);
1047 return XmlConvert.ToString ((Char) o);
1048 case TypeCode.DateTime:
1049 return XmlConvert.ToString ((DateTime) o);
1050 case TypeCode.Decimal:
1051 return XmlConvert.ToString ((Decimal) o);
1052 case TypeCode.Double:
1053 return XmlConvert.ToString ((Double) o);
1054 case TypeCode.Int16:
1055 return XmlConvert.ToString ((Int16) o);
1056 case TypeCode.Int32:
1057 return XmlConvert.ToString ((Int32) o);
1058 case TypeCode.Int64:
1059 return XmlConvert.ToString ((Int64) o);
1060 case TypeCode.SByte:
1061 return XmlConvert.ToString ((SByte) o);
1062 case TypeCode.Single:
1063 return XmlConvert.ToString ((Single) o);
1064 case TypeCode.UInt16:
1065 return XmlConvert.ToString ((UInt16) o);
1066 case TypeCode.UInt32:
1067 return XmlConvert.ToString ((UInt32) o);
1068 case TypeCode.UInt64:
1069 return XmlConvert.ToString ((UInt64) o);
1071 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
1072 if (o is Guid) return XmlConvert.ToString ((Guid) o);
1073 if (o is byte[]) return Convert.ToBase64String ((byte[])o);
1074 return o.ToString ();
1077 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
1079 //Write out each table in order, providing it is not
1080 //part of another table structure via a nested parent relationship
1081 foreach (DataTable table in tableCollection) {
1082 bool isTopLevel = true;
1083 foreach (DataRelation rel in table.ParentRelations) {
1091 WriteTable ( writer, table, mode, version);
1096 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
1098 DataRow[] rows = new DataRow [table.Rows.Count];
1099 table.Rows.CopyTo (rows, 0);
1100 WriteTable (writer, rows, mode, version);
1103 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1105 //The columns can be attributes, hidden, elements, or simple content
1106 //There can be 0-1 simple content cols or 0-* elements
1107 System.Collections.ArrayList atts;
1108 System.Collections.ArrayList elements;
1109 DataColumn simple = null;
1111 if (rows.Length == 0) return;
1112 DataTable table = rows[0].Table;
1113 SplitColumns (table, out atts, out elements, out simple);
1114 //sort out the namespacing
1115 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1117 foreach (DataRow row in rows) {
1118 if (!row.HasVersion(version) ||
1119 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
1120 && version == DataRowVersion.Original))
1123 // First check are all the rows null. If they are we just write empty element
1124 bool AllNulls = true;
1125 foreach (DataColumn dc in table.Columns) {
1127 if (row [dc.ColumnName, version] != DBNull.Value) {
1133 // If all of the columns were null, we have to write empty element
1135 writer.WriteElementString (table.TableName, "");
1139 WriteTableElement (writer, mode, table, row, version);
1141 foreach (DataColumn col in atts) {
1142 WriteColumnAsAttribute (writer, mode, col, row, version);
1145 if (simple != null) {
1146 writer.WriteString (WriteObjectXml (row[simple, version]));
1149 foreach (DataColumn col in elements) {
1150 WriteColumnAsElement (writer, mode, col, row, version);
1154 foreach (DataRelation relation in table.ChildRelations) {
1155 if (relation.Nested) {
1156 WriteTable (writer, row.GetChildRows (relation), mode, version);
1160 writer.WriteEndElement ();
1165 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1167 string colnspc = null;
1168 object rowObject = row [col, version];
1170 if (rowObject == null || rowObject == DBNull.Value)
1173 if (col.Namespace != String.Empty)
1174 colnspc = col.Namespace;
1176 //TODO check if I can get away with write element string
1177 WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName);
1178 writer.WriteString (WriteObjectXml (rowObject));
1179 writer.WriteEndElement ();
1182 private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1184 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
1187 private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
1189 //sort out the namespacing
1190 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1192 WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
1194 if (mode == XmlWriteMode.DiffGram) {
1195 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
1196 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", row.XmlRowID.ToString());
1197 string modeName = null;
1198 if (row.RowState == DataRowState.Modified)
1199 modeName = "modified";
1200 else if (row.RowState == DataRowState.Added)
1201 modeName = "inserted";
1203 if (version != DataRowVersion.Original && modeName != null)
1204 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
1208 private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
1210 writer.WriteStartElement (prefix, name, nspc);
1213 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1216 case XmlWriteMode.WriteSchema:
1217 writer.WriteAttributeString (prefix, name, nspc);
1219 case XmlWriteMode.DiffGram:
1220 writer.WriteAttributeString (prefix, name, nspc,stringValue);
1223 writer.WriteAttributeString (name, stringValue);
1228 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
1230 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
1232 if (mode == XmlWriteMode.DiffGram) {
1233 SetTableRowsID (table);
1234 WriteDiffGramElement (writer);
1237 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
1239 WriteTable (writer, table, mode, DataRowVersion.Default);
1241 if (mode == XmlWriteMode.DiffGram) {
1242 writer.WriteEndElement (); //DataSet name
1243 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
1245 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
1246 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
1247 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
1248 writer.WriteEndElement ();
1251 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
1254 XmlSchema IXmlSerializable.GetSchema ()
1256 return BuildSchema ();
1259 XmlSchema BuildSchema ()
1261 return BuildSchema (Tables, Relations);
1264 internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
1266 string constraintPrefix = "";
1267 XmlSchema schema = new XmlSchema ();
1269 schema.Namespaces.Add("xs", XmlSchema.Namespace);
1270 schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1272 if (Namespace != "") {
1273 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1274 schema.ElementFormDefault = XmlSchemaForm.Qualified;
1275 schema.TargetNamespace = Namespace;
1276 schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
1277 constraintPrefix = XmlConstants.TnsPrefix + ":";
1280 // Namespaces defined in tables and columns
1281 // FIXME: What if the same prefix is mapped? Create another
1282 // prefix and apply them. (But how?)
1283 foreach (DataTable dt in tables) {
1284 if (dt.Namespace != String.Empty)
1285 schema.Namespaces.Add (dt.Prefix, dt.Namespace);
1286 foreach (DataColumn col in dt.Columns)
1287 if (col.Namespace != String.Empty)
1288 schema.Namespaces.Add (col.Prefix, col.Namespace);
1291 // set the schema id
1292 schema.Id = DataSetName;
1293 XmlDocument doc = new XmlDocument ();
1294 XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
1295 xmlnsAttr.Value = Namespace;
1297 schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
1299 XmlSchemaElement elem = new XmlSchemaElement ();
1300 elem.Name = XmlConvert.EncodeName (DataSetName);
1302 XmlAttribute[] atts = new XmlAttribute [2];
1303 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1304 atts[0].Value = "true";
1306 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1307 atts[1].Value = locale.Name;
1309 elem.UnhandledAttributes = atts;
1311 schema.Items.Add (elem);
1313 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1314 elem.SchemaType = complex;
1316 XmlSchemaChoice choice = new XmlSchemaChoice ();
1317 complex.Particle = choice;
1318 choice.MaxOccursString = XmlConstants.Unbounded;
1320 //Write out schema for each table in order
1321 foreach (DataTable table in tables) {
1322 bool isTopLevel = true;
1323 foreach (DataRelation rel in table.ParentRelations) {
1331 choice.Items.Add (GetTableSchema (doc, table));
1335 AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
1339 // Add all constraints in all tables to the schema.
1340 private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
1342 // first add all unique constraints.
1343 Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
1344 // Add all foriegn key constraints.
1345 AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
1348 // Add unique constaraints to the schema.
1349 // return hashtable with the names of all XmlSchemaUnique elements we created.
1350 private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
1352 XmlDocument doc = new XmlDocument();
1353 Hashtable uniqueNames = new Hashtable();
1354 foreach (DataTable table in tables) {
1356 foreach (Constraint constaint in table.Constraints) {
1358 if (constaint is UniqueConstraint) {
1359 ArrayList attrs = new ArrayList ();
1360 XmlAttribute attrib;
1361 UniqueConstraint uqConst = (UniqueConstraint)constaint;
1362 XmlSchemaUnique uniq = new XmlSchemaUnique ();
1364 // if column of the constraint is hidden do not write the constraint.
1365 bool isHidden = false;
1366 foreach (DataColumn column in uqConst.Columns) {
1367 if (column.ColumnMapping == MappingType.Hidden) {
1376 // if constaraint name do not exist in the hashtable we can use it.
1377 if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
1378 uniq.Name = uqConst.ConstraintName;
1380 // generate new constraint name for the XmlSchemaUnique element.
1382 uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
1383 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1384 attrib.Value = uqConst.ConstraintName;
1387 if (uqConst.IsPrimaryKey) {
1388 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
1389 attrib.Value = "true";
1393 uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1395 uniq.Selector = new XmlSchemaXPath();
1396 uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
1397 XmlSchemaXPath field;
1398 foreach (DataColumn column in uqConst.Columns) {
1399 field = new XmlSchemaXPath();
1400 field.XPath = constraintPrefix+column.ColumnName;
1401 uniq.Fields.Add(field);
1404 elem.Constraints.Add (uniq);
1405 uniqueNames.Add (uniq.Name, null);
1412 // Add the foriegn keys to the schema.
1413 private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
1415 if (relations == null) return;
1417 XmlDocument doc = new XmlDocument();
1418 foreach (DataRelation rel in relations) {
1420 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
1423 ArrayList attrs = new ArrayList ();
1424 XmlAttribute attrib;
1425 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1426 keyRef.Name = rel.RelationName;
1427 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1428 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1430 string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
1431 // first try to find the concatenated name. If we didn't find it - use constraint name.
1432 if (uniqueNames.ContainsKey (concatName)) {
1433 keyRef.Refer = new XmlQualifiedName(concatName);
1436 keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
1440 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1441 attrib.Value = "true";
1445 keyRef.Selector = new XmlSchemaXPath();
1446 keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
1447 XmlSchemaXPath field;
1448 foreach (DataColumn column in rel.ChildColumns) {
1449 field = new XmlSchemaXPath();
1450 field.XPath = constraintPrefix+column.ColumnName;
1451 keyRef.Fields.Add(field);
1453 keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1454 elem.Constraints.Add (keyRef);
1458 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1464 SplitColumns (table, out atts, out elements, out simple);
1466 XmlSchemaElement elem = new XmlSchemaElement ();
1467 elem.Name = table.TableName;
1469 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1470 elem.SchemaType = complex;
1472 //TODO - what about the simple content?
1473 if (simple != null) {
1474 // add simpleContent
1475 XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
1476 complex.ContentModel = simpleContent;
1478 // add column name attribute
1479 XmlAttribute[] xlmAttrs = new XmlAttribute [2];
1480 xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
1481 xlmAttrs[0].Value = simple.ColumnName;
1483 // add ordinal attribute
1484 xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
1485 xlmAttrs[1].Value = simple.Ordinal.ToString();
1486 simpleContent.UnhandledAttributes = xlmAttrs;
1490 XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
1491 simpleContent.Content = extension;
1492 extension.BaseTypeName = MapType (simple.DataType);
1496 //A sequence of element types or a simple content node
1498 XmlSchemaSequence seq = new XmlSchemaSequence ();
1499 complex.Particle = seq;
1501 foreach (DataColumn col in elements) {
1503 // Add element for the column.
1504 XmlSchemaElement colElem = new XmlSchemaElement ();
1505 ArrayList xattrs = new ArrayList();
1507 colElem.Name = col.ColumnName;
1509 if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
1510 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1511 xattr.Value = col.Caption;
1515 if (col.AutoIncrement == true) {
1516 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
1517 xattr.Value = "true";
1521 if (col.AutoIncrementSeed != 0) {
1522 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
1523 xattr.Value = col.AutoIncrementSeed.ToString();
1527 if (col.DefaultValue.ToString () != String.Empty)
1528 colElem.DefaultValue = col.DefaultValue.ToString ();
1530 if (col.MaxLength < 0)
1531 colElem.SchemaTypeName = MapType (col.DataType);
1533 if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string)
1534 && col.DataType != typeof (char)) {
1535 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
1536 xattr.Value = col.DataType.ToString();
1540 if (col.AllowDBNull) {
1541 colElem.MinOccurs = 0;
1544 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
1545 // XmlConstants.Ordinal,
1546 // XmlConstants.MsdataNamespace,
1547 // col.Ordinal.ToString ());
1549 // Write SimpleType if column have MaxLength
1550 if (col.MaxLength > -1) {
1551 colElem.SchemaType = GetTableSimpleType (doc, col);
1554 colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
1555 seq.Items.Add (colElem);
1558 foreach (DataRelation rel in table.ChildRelations) {
1560 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1565 //Then a list of attributes
1566 foreach (DataColumn col in atts) {
1567 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1568 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1569 att.Name = col.ColumnName;
1570 att.Form = XmlSchemaForm.Unqualified;
1571 att.SchemaTypeName = MapType (col.DataType);
1572 complex.Attributes.Add (att);
1578 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1581 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1584 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1585 restriction.BaseTypeName = MapType (col.DataType);
1588 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1589 max.Value = XmlConvert.ToString (col.MaxLength);
1590 restriction.Facets.Add (max);
1592 simple.Content = restriction;
1596 private void DoWriteXmlSchema (XmlWriter writer)
1598 BuildSchema ().Write (writer);
1602 /// Helper function to split columns into attributes elements and simple
1605 private void SplitColumns (DataTable table,
1607 out ArrayList elements,
1608 out DataColumn simple)
1610 //The columns can be attributes, hidden, elements, or simple content
1611 //There can be 0-1 simple content cols or 0-* elements
1612 atts = new System.Collections.ArrayList ();
1613 elements = new System.Collections.ArrayList ();
1616 //Sort out the columns
1617 foreach (DataColumn col in table.Columns) {
1618 switch (col.ColumnMapping) {
1619 case MappingType.Attribute:
1622 case MappingType.Element:
1625 case MappingType.SimpleContent:
1626 if (simple != null) {
1627 throw new System.InvalidOperationException ("There may only be one simple content element");
1632 //ignore Hidden elements
1638 private void WriteDiffGramElement(XmlWriter writer)
1640 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
1641 WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1644 private void SetRowsID()
1646 foreach (DataTable Table in Tables)
1647 SetTableRowsID (Table);
1650 private void SetTableRowsID (DataTable Table)
1653 foreach (DataRow Row in Table.Rows) {
1654 Row.XmlRowID = dataRowID;
1660 private XmlQualifiedName MapType (Type type)
1662 switch (Type.GetTypeCode (type)) {
1663 case TypeCode.String: return XmlConstants.QnString;
1664 case TypeCode.Int16: return XmlConstants.QnShort;
1665 case TypeCode.Int32: return XmlConstants.QnInt;
1666 case TypeCode.Int64: return XmlConstants.QnLong;
1667 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1668 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1669 //case TypeCode.Char: return XmlConstants.QnChar;
1670 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1671 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1672 case TypeCode.Double: return XmlConstants.QnDouble;
1673 case TypeCode.SByte: return XmlConstants.QnSbyte;
1674 case TypeCode.Single: return XmlConstants.QnFloat;
1675 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1676 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1677 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1680 if (typeof (TimeSpan) == type)
1681 return XmlConstants.QnDuration;
1682 else if (typeof (System.Uri) == type)
1683 return XmlConstants.QnUri;
1684 else if (typeof (byte[]) == type)
1685 return XmlConstants.QnBase64Binary;
1686 else if (typeof (XmlQualifiedName) == type)
1687 return XmlConstants.QnXmlQualifiedName;
1689 return XmlConstants.QnString;
1692 #endregion //Private Xml Serialisation