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;
46 internal XmlDataDocument _xmlDataDocument = null;
50 public DataSet () : this ("NewDataSet")
54 public DataSet (string name)
57 tableCollection = new DataTableCollection (this);
58 relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
59 properties = new PropertyCollection ();
60 this.prefix = String.Empty;
62 this.Locale = CultureInfo.CurrentCulture;
66 protected DataSet (SerializationInfo info, StreamingContext context) : this ()
68 throw new NotImplementedException ();
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 foreach (DataTable T in Tables) {
84 if (T.VirginCaseSensitive)
85 T.CaseSensitive = value;
88 caseSensitive = value;
90 foreach (DataTable table in Tables) {
91 foreach (Constraint c in table.Constraints)
92 c.AssertConstraint ();
98 [DataCategory ("Data")]
99 [DataSysDescription ("The name of this DataSet.")]
101 public string DataSetName {
102 get { return dataSetName; }
103 set { dataSetName = value; }
106 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
108 public DataViewManager DefaultViewManager {
110 if (defaultView == null)
111 defaultView = new DataViewManager (this);
116 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
117 [DefaultValue (true)]
118 public bool EnforceConstraints {
119 get { return enforceConstraints; }
121 if (value != enforceConstraints) {
122 enforceConstraints = value;
124 foreach (DataTable table in Tables) {
125 // first assert all unique constraints
126 foreach (UniqueConstraint uc in table.Constraints.UniqueConstraints)
127 uc.AssertConstraint ();
128 // then assert all foreign keys
129 foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
130 fk.AssertConstraint ();
138 [DataCategory ("Data")]
139 [DataSysDescription ("The collection that holds custom user information.")]
140 public PropertyCollection ExtendedProperties {
141 get { return properties; }
145 [DataSysDescription ("Indicates that the DataSet has errors.")]
146 public bool HasErrors {
149 for (int i = 0; i < Tables.Count; i++) {
150 if (Tables[i].HasErrors)
157 [DataCategory ("Data")]
158 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
159 public CultureInfo Locale {
164 if (locale == null || !locale.Equals (value)) {
165 // TODO: check if the new locale is valid
166 // TODO: update locale of all tables
172 public void Merge (DataRow[] rows)
174 Merge (rows, false, MissingSchemaAction.Add);
177 public void Merge (DataSet dataSet)
179 Merge (dataSet, false, MissingSchemaAction.Add);
182 public void Merge (DataTable table)
184 Merge (table, false, MissingSchemaAction.Add);
187 public void Merge (DataSet dataSet, bool preserveChanges)
189 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
193 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
196 throw new ArgumentNullException ("rows");
197 if (!IsLegalSchemaAction (missingSchemaAction))
198 throw new ArgumentOutOfRangeException ("missingSchemaAction");
200 MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
204 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
207 throw new ArgumentNullException ("dataSet");
208 if (!IsLegalSchemaAction (missingSchemaAction))
209 throw new ArgumentOutOfRangeException ("missingSchemaAction");
211 MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
215 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
218 throw new ArgumentNullException ("table");
219 if (!IsLegalSchemaAction (missingSchemaAction))
220 throw new ArgumentOutOfRangeException ("missingSchemaAction");
222 MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
225 private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
227 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
228 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
233 [DataCategory ("Data")]
234 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
236 public string Namespace {
238 get { return _namespace; }
241 //TODO - trigger an event if this happens?
246 [DataCategory ("Data")]
247 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
249 public string Prefix {
251 get { return prefix; }
254 //TODO - trigger an event if this happens?
257 value = string.Empty;
259 if (value != this.prefix)
260 RaisePropertyChanging ("Prefix");
265 [DataCategory ("Data")]
266 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
267 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
268 public DataRelationCollection Relations {
270 return relationCollection;
275 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
276 public override ISite Site {
279 throw new NotImplementedException ();
284 throw new NotImplementedException ();
288 [DataCategory ("Data")]
289 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
290 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
291 public DataTableCollection Tables {
292 get { return tableCollection; }
295 #endregion // Public Properties
297 #region Public Methods
300 public void AcceptChanges ()
302 foreach (DataTable tempTable in tableCollection)
303 tempTable.AcceptChanges ();
308 if (_xmlDataDocument != null)
309 throw new NotSupportedException ("Clear function on dataset and datatable is not supported on XmlDataDocument.");
310 for (int t = 0; t < tableCollection.Count; t++) {
311 tableCollection[t].Clear ();
315 public virtual DataSet Clone ()
317 DataSet Copy = new DataSet ();
318 CopyProperties (Copy);
320 foreach (DataTable Table in Tables) {
321 Copy.Tables.Add (Table.Clone ());
324 //Copy Relationships between tables after existance of tables
325 //and setting properties correctly
326 CopyRelations (Copy);
331 // Copies both the structure and data for this DataSet.
332 public DataSet Copy ()
334 DataSet Copy = new DataSet ();
335 CopyProperties (Copy);
337 // Copy DatSet's tables
338 foreach (DataTable Table in Tables)
339 Copy.Tables.Add (Table.Copy ());
341 //Copy Relationships between tables after existance of tables
342 //and setting properties correctly
343 CopyRelations (Copy);
349 private void CopyProperties (DataSet Copy)
351 Copy.CaseSensitive = CaseSensitive;
352 //Copy.Container = Container
353 Copy.DataSetName = DataSetName;
354 //Copy.DefaultViewManager
356 Copy.EnforceConstraints = EnforceConstraints;
357 //Copy.ExtendedProperties
359 //Copy.Locale = Locale;
360 Copy.Namespace = Namespace;
361 Copy.Prefix = Prefix;
367 private void CopyRelations (DataSet Copy)
370 //Creation of the relation contains some of the properties, and the constructor
371 //demands these values. instead changing the DataRelation constructor and behaviour the
372 //parameters are pre-configured and sent to the most general constructor
374 foreach (DataRelation MyRelation in this.Relations) {
375 string pTable = MyRelation.ParentTable.TableName;
376 string cTable = MyRelation.ChildTable.TableName;
377 DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length];
378 DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
381 foreach (DataColumn DC in MyRelation.ParentColumns) {
382 P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
388 foreach (DataColumn DC in MyRelation.ChildColumns) {
389 C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
393 DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
394 //cRel.ChildColumns = MyRelation.ChildColumns;
395 //cRel.ChildTable = MyRelation.ChildTable;
396 //cRel.ExtendedProperties = cRel.ExtendedProperties;
397 //cRel.Nested = MyRelation.Nested;
398 //cRel.ParentColumns = MyRelation.ParentColumns;
399 //cRel.ParentTable = MyRelation.ParentTable;
401 Copy.Relations.Add (cRel);
408 public DataSet GetChanges ()
410 return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
414 public DataSet GetChanges (DataRowState rowStates)
416 if (!HasChanges (rowStates))
419 DataSet copySet = Clone ();
420 Hashtable addedRows = new Hashtable ();
422 IEnumerator tableEnumerator = Tables.GetEnumerator ();
425 while (tableEnumerator.MoveNext ()) {
426 origTable = (DataTable)tableEnumerator.Current;
427 copyTable = copySet.Tables[origTable.TableName];
429 // Look for relations that have this table as child
430 IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
432 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
433 while (rowEnumerator.MoveNext ()) {
434 DataRow row = (DataRow)rowEnumerator.Current;
436 if (row.IsRowChanged (rowStates))
437 AddChangedRow (addedRows, copySet, copyTable, relations, row);
443 void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
445 if (addedRows.ContainsKey (row)) return;
448 while (relations.MoveNext ()) {
449 DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
450 if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
451 DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
452 AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
455 DataRow newRow = copyTable.NewRow ();
456 copyTable.Rows.Add (newRow);
457 row.CopyValuesToRow (newRow);
458 newRow.XmlRowID = row.XmlRowID;
459 addedRows.Add (row,row);
464 public DataTableReader GetDataReader (DataTable[] dataTables)
466 throw new NotImplementedException ();
470 public DataTableReader GetDataReader ()
472 throw new NotImplementedException ();
476 public string GetXml ()
478 StringWriter Writer = new StringWriter ();
480 // Sending false for not printing the Processing instruction
481 WriteXml (Writer, XmlWriteMode.IgnoreSchema, false);
482 return Writer.ToString ();
485 public string GetXmlSchema ()
487 StringWriter Writer = new StringWriter ();
488 WriteXmlSchema (Writer);
489 return Writer.ToString ();
493 public bool HasChanges ()
495 return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
499 public bool HasChanges (DataRowState rowState)
501 if (((int)rowState & 0xffffffe0) != 0)
502 throw new ArgumentOutOfRangeException ("rowState");
504 DataTableCollection tableCollection = Tables;
506 DataRowCollection rowCollection;
509 for (int i = 0; i < tableCollection.Count; i++) {
510 table = tableCollection[i];
511 rowCollection = table.Rows;
512 for (int j = 0; j < rowCollection.Count; j++) {
513 row = rowCollection[j];
514 if ((row.RowState & rowState) != 0)
523 public void InferXmlSchema (XmlReader reader, string[] nsArray)
527 public void InferXmlSchema (Stream stream, string[] nsArray)
529 InferXmlSchema (new XmlTextReader (stream), nsArray);
532 public void InferXmlSchema (TextReader reader, string[] nsArray)
534 InferXmlSchema (new XmlTextReader (reader), nsArray);
537 public void InferXmlSchema (string fileName, string[] nsArray)
539 XmlTextReader reader = new XmlTextReader (fileName);
541 InferXmlSchema (reader, nsArray);
549 public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
551 throw new NotImplementedException ();
555 public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
557 throw new NotImplementedException ();
561 public virtual void RejectChanges ()
564 bool oldEnforceConstraints = this.EnforceConstraints;
565 this.EnforceConstraints = false;
567 for (i = 0; i < this.Tables.Count;i++)
568 this.Tables[i].RejectChanges ();
570 this.EnforceConstraints = oldEnforceConstraints;
573 public virtual void Reset ()
575 IEnumerator constraintEnumerator;
577 // first we remove all ForeignKeyConstraints (if we will not do that
578 // we will get an exception when clearing the tables).
579 for (int i = 0; i < Tables.Count; i++) {
580 ConstraintCollection cc = Tables[i].Constraints;
581 for (int j = 0; j < cc.Count; j++) {
582 if (cc[j] is ForeignKeyConstraint)
592 public void WriteXml (Stream stream)
594 XmlTextWriter writer = new XmlTextWriter (stream, null);
595 writer.Formatting = Formatting.Indented;
600 /// Writes the current data for the DataSet to the specified file.
602 /// <param name="filename">Fully qualified filename to write to</param>
603 public void WriteXml (string fileName)
605 XmlTextWriter writer = new XmlTextWriter (fileName, null);
606 writer.Formatting = Formatting.Indented;
616 public void WriteXml (TextWriter writer)
618 XmlTextWriter xwriter = new XmlTextWriter (writer);
619 xwriter.Formatting = Formatting.Indented;
623 public void WriteXml (XmlWriter writer)
625 WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
628 public void WriteXml (string filename, XmlWriteMode mode)
630 XmlTextWriter writer = new XmlTextWriter (filename, null);
631 writer.Formatting = Formatting.Indented;
634 WriteXml (writer, mode, true);
641 public void WriteXml (Stream stream, XmlWriteMode mode)
643 XmlTextWriter writer = new XmlTextWriter (stream, null);
644 writer.Formatting = Formatting.Indented;
645 WriteXml (writer, mode, true);
648 public void WriteXml (TextWriter writer, XmlWriteMode mode)
650 XmlTextWriter xwriter = new XmlTextWriter (writer);
651 xwriter.Formatting = Formatting.Indented;
652 WriteXml (xwriter, mode, true);
655 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
657 WriteXml (writer, mode, true);
660 internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
662 XmlTextWriter writer = new XmlTextWriter (stream, null);
663 writer.Formatting = Formatting.Indented;
664 WriteXml (writer, mode, writePI);
667 internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
669 XmlTextWriter writer = new XmlTextWriter (fileName, null);
670 writer.Formatting = Formatting.Indented;
673 WriteXml (writer, mode, writePI);
680 internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
682 XmlTextWriter xwriter = new XmlTextWriter (writer);
683 xwriter.Formatting = Formatting.Indented;
684 WriteXml (xwriter, mode, writePI);
687 internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
689 if (writePI && (writer.WriteState == WriteState.Start))
690 writer.WriteStartDocument (true);
692 if (mode == XmlWriteMode.DiffGram) {
694 WriteDiffGramElement(writer);
697 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
699 /*********************************************************
700 * This is a patch for interoperability with ms.net. *
701 * Because in web services the .net client expects this *
702 * atrribute even if namespace is an empty string *
703 ********************************************************/
704 if (Namespace == null || Namespace.Length == 0)
705 WriteAttributeString (writer, mode, null, null, "xmlns", Namespace);
707 if (mode == XmlWriteMode.WriteSchema) {
708 DoWriteXmlSchema (writer);
711 WriteTables (writer, mode, Tables, DataRowVersion.Default);
712 if (mode == XmlWriteMode.DiffGram) {
713 writer.WriteEndElement (); //DataSet name
714 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
716 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
717 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
718 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
719 writer.WriteEndElement ();
722 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
725 public void WriteXmlSchema (Stream stream)
727 XmlTextWriter writer = new XmlTextWriter (stream, null );
728 writer.Formatting = Formatting.Indented;
729 WriteXmlSchema (writer);
732 public void WriteXmlSchema (string fileName)
734 XmlTextWriter writer = new XmlTextWriter (fileName, null);
735 writer.Formatting = Formatting.Indented;
737 WriteXmlSchema (writer);
744 public void WriteXmlSchema (TextWriter writer)
746 XmlTextWriter xwriter = new XmlTextWriter (writer);
747 xwriter.Formatting = Formatting.Indented;
748 WriteXmlSchema (xwriter);
751 public void WriteXmlSchema (XmlWriter writer)
753 //Create a skeleton doc and then write the schema
754 //proper which is common to the WriteXml method in schema mode
755 writer.WriteStartDocument ();
756 DoWriteXmlSchema (writer);
758 writer.WriteEndDocument ();
761 public void ReadXmlSchema (Stream stream)
763 XmlReader reader = new XmlTextReader (stream, null);
764 ReadXmlSchema (reader);
767 public void ReadXmlSchema (string str)
769 XmlReader reader = new XmlTextReader (str);
771 ReadXmlSchema (reader);
778 public void ReadXmlSchema (TextReader treader)
780 XmlReader reader = new XmlTextReader (treader);
781 ReadXmlSchema (reader);
784 public void ReadXmlSchema (XmlReader reader)
786 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
787 SchemaMapper.Read (reader);
790 public XmlReadMode ReadXml (Stream stream)
792 return ReadXml (new XmlTextReader (stream));
795 public XmlReadMode ReadXml (string str)
797 XmlTextReader reader = new XmlTextReader (str);
799 return ReadXml (reader);
806 public XmlReadMode ReadXml (TextReader reader)
808 return ReadXml (new XmlTextReader (reader));
811 public XmlReadMode ReadXml (XmlReader r)
813 XmlDataLoader Loader = new XmlDataLoader (this);
814 // FIXME: somekinda exception?
816 return XmlReadMode.Auto; // FIXME
818 // Check if the curent element is the process instruction (PI).
819 // if it is move to next element.
820 if (r.LocalName == "xml")
823 // The document can be diffgram if :
824 // 1. The first element is diffgram.
825 if (r.LocalName == "diffgram") {
826 return ReadXml (r, XmlReadMode.DiffGram);
829 bool schemaRead = false;
830 if (r.LocalName == "schema") {
836 // If we read the schema the next element can be a diffgram
837 // that is what happen in web services soap message.
838 if (schemaRead && r.LocalName == "diffgram") {
839 return ReadXml (r, XmlReadMode.DiffGram);
842 // Get the DataSet name.
843 // if this xml is not diffgram then the first element will be the
845 string dataSetName = XmlConvert.DecodeName (r.LocalName);
846 DataSetName = dataSetName;
848 r.ReadStartElement ();
852 // After reading the dataset name there can be three scenarios:
853 // 1. The next part will be the schema of the dataset.
854 // 2. The next part will be the data of the dataset using diffgram.
855 // 3. The next part will be the data of tha dataset without diffgram.
856 // Check if the current element is the schema
857 if (r.LocalName == "schema") {
863 // check if the data was written in a diffgram mode.
864 if (r.LocalName == "diffgram") {
865 return ReadXml (r, XmlReadMode.DiffGram);
868 // If the schema has been read we should read the rest data of the dataset
869 // with ignoreschema mode.
871 ReadXml (r, XmlReadMode.IgnoreSchema, false);
872 return XmlReadMode.ReadSchema;
875 // Read the data of the dataset with inferschema.
876 return ReadXml (r, XmlReadMode.InferSchema, false);
880 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
882 return ReadXml (new XmlTextReader (stream), mode);
885 public XmlReadMode ReadXml (string str, XmlReadMode mode)
887 XmlTextReader reader = new XmlTextReader (str);
889 return ReadXml (reader, mode);
896 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
898 return ReadXml (new XmlTextReader (reader), mode);
902 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
904 // we have to initiate the reader.
905 if (reader.ReadState == ReadState.Initial)
908 // Check if the curent element is the process instruction (PI).
909 // if it is move to next element.
910 if (reader.LocalName == "xml")
911 reader.MoveToContent();
913 XmlReadMode Result = XmlReadMode.Auto;
915 if (mode == XmlReadMode.DiffGram) {
916 if (reader.LocalName != "diffgram"){
917 reader.MoveToContent ();
918 reader.ReadStartElement (); // <DataSet>
920 reader.MoveToContent ();
921 if (reader.LocalName == "schema")
922 ReadXmlSchema (reader);
924 reader.MoveToContent ();
926 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
927 DiffLoader.Load (reader);
928 Result = XmlReadMode.DiffGram;
931 Result = ReadXml(reader, mode, true);
936 private XmlReadMode ReadXml (XmlReader r, XmlReadMode mode, bool readDataSet) {
939 string dataSetName = XmlConvert.DecodeName (r.LocalName);
940 DataSetName = dataSetName;
941 // get the Namespace of the DataSet.
942 string tmp = r.GetAttribute("xmlns");
946 r.ReadStartElement ();
950 XmlDataLoader Loader = new XmlDataLoader (this);
951 return Loader.LoadData (r, mode);
954 #endregion // Public Methods
956 #region Public Events
958 [DataCategory ("Action")]
959 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
960 public event MergeFailedEventHandler MergeFailed;
962 #endregion // Public Events
970 #endregion Destructors
972 #region IListSource methods
973 IList IListSource.GetList ()
975 return DefaultViewManager;
978 bool IListSource.ContainsListCollection {
983 #endregion IListSource methods
985 #region ISupportInitialize methods
986 public void BeginInit ()
990 public void EndInit ()
995 #region ISerializable
996 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
998 throw new NotImplementedException ();
1002 #region Protected Methods
1003 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
1005 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
1006 if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s)));
1010 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
1015 protected virtual void ReadXmlSerializable (XmlReader reader)
1017 ReadXml (reader, XmlReadMode.DiffGram); // FIXME
1020 void IXmlSerializable.ReadXml (XmlReader reader)
1023 ReadXmlSerializable(reader);
1025 // the XmlSerializationReader does this lines!!!
1026 //reader.MoveToContent ();
1027 //reader.ReadEndElement (); // </DataSet>
1030 void IXmlSerializable.WriteXml (XmlWriter writer)
1032 DoWriteXmlSchema (writer);
1033 WriteXml (writer, XmlWriteMode.DiffGram, true);
1036 protected virtual bool ShouldSerializeRelations ()
1041 protected virtual bool ShouldSerializeTables ()
1047 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
1052 protected virtual void OnRemoveRelation (DataRelation relation)
1057 protected virtual void OnRemoveTable (DataTable table)
1061 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
1063 if (MergeFailed != null)
1064 MergeFailed (this, e);
1068 protected internal void RaisePropertyChanging (string name)
1073 #region Private Xml Serialisation
1075 private string WriteObjectXml (object o)
1077 switch (Type.GetTypeCode (o.GetType ())) {
1078 case TypeCode.Boolean:
1079 return XmlConvert.ToString ((Boolean) o);
1081 return XmlConvert.ToString ((Byte) o);
1083 return XmlConvert.ToString ((Char) o);
1084 case TypeCode.DateTime:
1085 return XmlConvert.ToString ((DateTime) o);
1086 case TypeCode.Decimal:
1087 return XmlConvert.ToString ((Decimal) o);
1088 case TypeCode.Double:
1089 return XmlConvert.ToString ((Double) o);
1090 case TypeCode.Int16:
1091 return XmlConvert.ToString ((Int16) o);
1092 case TypeCode.Int32:
1093 return XmlConvert.ToString ((Int32) o);
1094 case TypeCode.Int64:
1095 return XmlConvert.ToString ((Int64) o);
1096 case TypeCode.SByte:
1097 return XmlConvert.ToString ((SByte) o);
1098 case TypeCode.Single:
1099 return XmlConvert.ToString ((Single) o);
1100 case TypeCode.UInt16:
1101 return XmlConvert.ToString ((UInt16) o);
1102 case TypeCode.UInt32:
1103 return XmlConvert.ToString ((UInt32) o);
1104 case TypeCode.UInt64:
1105 return XmlConvert.ToString ((UInt64) o);
1107 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
1108 if (o is Guid) return XmlConvert.ToString ((Guid) o);
1109 if (o is byte[]) return Convert.ToBase64String ((byte[])o);
1110 return o.ToString ();
1113 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
1115 //Write out each table in order, providing it is not
1116 //part of another table structure via a nested parent relationship
1117 foreach (DataTable table in tableCollection) {
1118 bool isTopLevel = true;
1119 foreach (DataRelation rel in table.ParentRelations) {
1127 WriteTable ( writer, table, mode, version);
1132 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
1134 DataRow[] rows = new DataRow [table.Rows.Count];
1135 table.Rows.CopyTo (rows, 0);
1136 WriteTable (writer, rows, mode, version);
1139 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1141 //The columns can be attributes, hidden, elements, or simple content
1142 //There can be 0-1 simple content cols or 0-* elements
1143 System.Collections.ArrayList atts;
1144 System.Collections.ArrayList elements;
1145 DataColumn simple = null;
1147 if (rows.Length == 0) return;
1148 DataTable table = rows[0].Table;
1149 SplitColumns (table, out atts, out elements, out simple);
1150 //sort out the namespacing
1151 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1153 foreach (DataRow row in rows) {
1154 if (!row.HasVersion(version) ||
1155 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
1156 && version == DataRowVersion.Original))
1159 // First check are all the rows null. If they are we just write empty element
1160 bool AllNulls = true;
1161 foreach (DataColumn dc in table.Columns) {
1163 if (row [dc.ColumnName, version] != DBNull.Value) {
1169 // If all of the columns were null, we have to write empty element
1171 writer.WriteElementString (table.TableName, "");
1175 WriteTableElement (writer, mode, table, row, version);
1177 foreach (DataColumn col in atts) {
1178 WriteColumnAsAttribute (writer, mode, col, row, version);
1181 if (simple != null) {
1182 writer.WriteString (WriteObjectXml (row[simple, version]));
1185 foreach (DataColumn col in elements) {
1186 WriteColumnAsElement (writer, mode, nspc, col, row, version);
1190 foreach (DataRelation relation in table.ChildRelations) {
1191 if (relation.Nested) {
1192 WriteTable (writer, row.GetChildRows (relation), mode, version);
1196 writer.WriteEndElement ();
1201 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
1203 string colnspc = nspc;
1204 object rowObject = row [col, version];
1206 if (rowObject == null || rowObject == DBNull.Value)
1209 if (col.Namespace != null) {
1210 colnspc = col.Namespace;
1213 //TODO check if I can get away with write element string
1214 WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName);
1215 writer.WriteString (WriteObjectXml (rowObject));
1216 writer.WriteEndElement ();
1219 private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
1221 WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ());
1224 private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
1226 //sort out the namespacing
1227 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1229 WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName);
1231 if (mode == XmlWriteMode.DiffGram) {
1232 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
1233 WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", row.XmlRowID.ToString());
1234 string modeName = null;
1235 if (row.RowState == DataRowState.Modified)
1236 modeName = "modified";
1237 else if (row.RowState == DataRowState.Added)
1238 modeName = "inserted";
1240 if (version != DataRowVersion.Original && modeName != null)
1241 WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
1245 private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
1247 if (nspc == null || nspc == "") {
1248 writer.WriteStartElement (name);
1250 else if (prefix != null) {
1251 writer.WriteStartElement (prefix, name, nspc);
1254 writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
1258 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1261 case XmlWriteMode.WriteSchema:
1262 writer.WriteAttributeString (prefix, name, nspc);
1264 case XmlWriteMode.DiffGram:
1265 writer.WriteAttributeString (prefix, name, nspc,stringValue);
1268 writer.WriteAttributeString (name, stringValue);
1273 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
1275 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
1277 if (mode == XmlWriteMode.DiffGram) {
1278 SetTableRowsID (table);
1279 WriteDiffGramElement (writer);
1282 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
1284 WriteTable (writer, table, mode, DataRowVersion.Default);
1286 if (mode == XmlWriteMode.DiffGram) {
1287 writer.WriteEndElement (); //DataSet name
1288 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
1290 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
1291 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
1292 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
1293 writer.WriteEndElement ();
1296 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
1299 XmlSchema IXmlSerializable.GetSchema ()
1301 return BuildSchema ();
1304 XmlSchema BuildSchema ()
1306 return BuildSchema (Tables, Relations);
1309 internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
1311 string constraintPrefix = "";
1312 XmlSchema schema = new XmlSchema ();
1314 schema.Namespaces.Add("xs", XmlSchema.Namespace);
1315 schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1317 if (Namespace != "" && Namespace != null) {
1318 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1319 schema.ElementFormDefault = XmlSchemaForm.Qualified;
1320 schema.TargetNamespace = Namespace;
1321 schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
1322 constraintPrefix = XmlConstants.TnsPrefix + ":";
1325 // set the schema id
1326 schema.Id = DataSetName;
1327 XmlDocument doc = new XmlDocument ();
1328 XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
1329 xmlnsAttr.Value = Namespace;
1331 schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
1333 XmlSchemaElement elem = new XmlSchemaElement ();
1334 elem.Name = XmlConvert.EncodeName (DataSetName);
1336 XmlAttribute[] atts = new XmlAttribute [2];
1337 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1338 atts[0].Value = "true";
1340 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1341 atts[1].Value = locale.Name;
1342 elem.UnhandledAttributes = atts;
1344 schema.Items.Add (elem);
1346 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1347 elem.SchemaType = complex;
1349 XmlSchemaChoice choice = new XmlSchemaChoice ();
1350 complex.Particle = choice;
1351 choice.MaxOccursString = XmlConstants.Unbounded;
1353 //Write out schema for each table in order
1354 foreach (DataTable table in tables) {
1355 bool isTopLevel = true;
1356 foreach (DataRelation rel in table.ParentRelations) {
1364 choice.Items.Add (GetTableSchema (doc, table));
1368 AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
1372 // Add all constraints in all tables to the schema.
1373 private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
1375 // first add all unique constraints.
1376 Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
1377 // Add all foriegn key constraints.
1378 AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
1381 // Add unique constaraints to the schema.
1382 // return hashtable with the names of all XmlSchemaUnique elements we created.
1383 private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
1385 XmlDocument doc = new XmlDocument();
1386 Hashtable uniqueNames = new Hashtable();
1387 foreach (DataTable table in tables) {
1389 foreach (Constraint constaint in table.Constraints) {
1391 if (constaint is UniqueConstraint) {
1392 ArrayList attrs = new ArrayList ();
1393 XmlAttribute attrib;
1394 UniqueConstraint uqConst = (UniqueConstraint)constaint;
1395 XmlSchemaUnique uniq = new XmlSchemaUnique ();
1397 // if column of the constraint is hidden do not write the constraint.
1398 bool isHidden = false;
1399 foreach (DataColumn column in uqConst.Columns) {
1400 if (column.ColumnMapping == MappingType.Hidden) {
1409 // if constaraint name do not exist in the hashtable we can use it.
1410 if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
1411 uniq.Name = uqConst.ConstraintName;
1413 // generate new constraint name for the XmlSchemaUnique element.
1415 uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
1416 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1417 attrib.Value = uqConst.ConstraintName;
1420 if (uqConst.IsPrimaryKey) {
1421 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
1422 attrib.Value = "true";
1426 uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1428 uniq.Selector = new XmlSchemaXPath();
1429 uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
1430 XmlSchemaXPath field;
1431 foreach (DataColumn column in uqConst.Columns) {
1432 field = new XmlSchemaXPath();
1433 field.XPath = constraintPrefix+column.ColumnName;
1434 uniq.Fields.Add(field);
1437 elem.Constraints.Add (uniq);
1438 uniqueNames.Add (uniq.Name, null);
1445 // Add the foriegn keys to the schema.
1446 private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
1448 if (relations == null) return;
1450 XmlDocument doc = new XmlDocument();
1451 foreach (DataRelation rel in relations) {
1453 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
1456 ArrayList attrs = new ArrayList ();
1457 XmlAttribute attrib;
1458 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1459 keyRef.Name = rel.RelationName;
1460 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1461 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1463 string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
1464 // first try to find the concatenated name. If we didn't find it - use constraint name.
1465 if (uniqueNames.ContainsKey (concatName)) {
1466 keyRef.Refer = new XmlQualifiedName(concatName);
1469 keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
1473 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1474 attrib.Value = "true";
1478 keyRef.Selector = new XmlSchemaXPath();
1479 keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
1480 XmlSchemaXPath field;
1481 foreach (DataColumn column in rel.ChildColumns) {
1482 field = new XmlSchemaXPath();
1483 field.XPath = constraintPrefix+column.ColumnName;
1484 keyRef.Fields.Add(field);
1486 keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1487 elem.Constraints.Add (keyRef);
1491 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1497 SplitColumns (table, out atts, out elements, out simple);
1499 XmlSchemaElement elem = new XmlSchemaElement ();
1500 elem.Name = table.TableName;
1502 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1503 elem.SchemaType = complex;
1505 //TODO - what about the simple content?
1506 if (simple != null) {
1507 // add simpleContent
1508 XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
1509 complex.ContentModel = simpleContent;
1511 // add column name attribute
1512 XmlAttribute[] xlmAttrs = new XmlAttribute [2];
1513 xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
1514 xlmAttrs[0].Value = simple.ColumnName;
1516 // add ordinal attribute
1517 xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
1518 xlmAttrs[1].Value = simple.Ordinal.ToString();
1519 simpleContent.UnhandledAttributes = xlmAttrs;
1523 XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
1524 simpleContent.Content = extension;
1525 extension.BaseTypeName = MapType (simple.DataType);
1529 //A sequence of element types or a simple content node
1531 XmlSchemaSequence seq = new XmlSchemaSequence ();
1532 complex.Particle = seq;
1534 foreach (DataColumn col in elements) {
1536 // Add element for the column.
1537 XmlSchemaElement colElem = new XmlSchemaElement ();
1538 ArrayList xattrs = new ArrayList();
1540 colElem.Name = col.ColumnName;
1542 if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
1543 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1544 xattr.Value = col.Caption;
1548 if (col.AutoIncrement == true) {
1549 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
1550 xattr.Value = "true";
1554 if (col.AutoIncrementSeed != 0) {
1555 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
1556 xattr.Value = col.AutoIncrementSeed.ToString();
1560 if (col.DefaultValue.ToString () != String.Empty)
1561 colElem.DefaultValue = col.DefaultValue.ToString ();
1563 if (col.MaxLength < 0)
1564 colElem.SchemaTypeName = MapType (col.DataType);
1566 if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string)
1567 && col.DataType != typeof (char)) {
1568 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
1569 xattr.Value = col.DataType.ToString();
1573 if (col.AllowDBNull) {
1574 colElem.MinOccurs = 0;
1577 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
1578 // XmlConstants.Ordinal,
1579 // XmlConstants.MsdataNamespace,
1580 // col.Ordinal.ToString ());
1582 // Write SimpleType if column have MaxLength
1583 if (col.MaxLength > -1) {
1584 colElem.SchemaType = GetTableSimpleType (doc, col);
1587 colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
1588 seq.Items.Add (colElem);
1591 foreach (DataRelation rel in table.ChildRelations) {
1593 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1598 //Then a list of attributes
1599 foreach (DataColumn col in atts) {
1600 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1601 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1602 att.Name = col.ColumnName;
1603 att.Form = XmlSchemaForm.Unqualified;
1604 att.SchemaTypeName = MapType (col.DataType);
1605 complex.Attributes.Add (att);
1611 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1614 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1617 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1618 restriction.BaseTypeName = MapType (col.DataType);
1621 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1622 max.Value = XmlConvert.ToString (col.MaxLength);
1623 restriction.Facets.Add (max);
1625 simple.Content = restriction;
1629 private void DoWriteXmlSchema (XmlWriter writer)
1631 BuildSchema ().Write (writer);
1635 /// Helper function to split columns into attributes elements and simple
1638 private void SplitColumns (DataTable table,
1640 out ArrayList elements,
1641 out DataColumn simple)
1643 //The columns can be attributes, hidden, elements, or simple content
1644 //There can be 0-1 simple content cols or 0-* elements
1645 atts = new System.Collections.ArrayList ();
1646 elements = new System.Collections.ArrayList ();
1649 //Sort out the columns
1650 foreach (DataColumn col in table.Columns) {
1651 switch (col.ColumnMapping) {
1652 case MappingType.Attribute:
1655 case MappingType.Element:
1658 case MappingType.SimpleContent:
1659 if (simple != null) {
1660 throw new System.InvalidOperationException ("There may only be one simple content element");
1665 //ignore Hidden elements
1671 private void WriteDiffGramElement(XmlWriter writer)
1673 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
1674 WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1677 private void SetRowsID()
1679 foreach (DataTable Table in Tables)
1680 SetTableRowsID (Table);
1683 private void SetTableRowsID (DataTable Table)
1686 foreach (DataRow Row in Table.Rows) {
1687 Row.XmlRowID = dataRowID;
1693 private XmlQualifiedName MapType (Type type)
1695 switch (Type.GetTypeCode (type)) {
1696 case TypeCode.String: return XmlConstants.QnString;
1697 case TypeCode.Int16: return XmlConstants.QnShort;
1698 case TypeCode.Int32: return XmlConstants.QnInt;
1699 case TypeCode.Int64: return XmlConstants.QnLong;
1700 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1701 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1702 //case TypeCode.Char: return XmlConstants.QnChar;
1703 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1704 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1705 case TypeCode.Double: return XmlConstants.QnDouble;
1706 case TypeCode.SByte: return XmlConstants.QnSbyte;
1707 case TypeCode.Single: return XmlConstants.QnFloat;
1708 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1709 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1710 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1713 if (typeof (TimeSpan) == type)
1714 return XmlConstants.QnDuration;
1715 else if (typeof (System.Uri) == type)
1716 return XmlConstants.QnUri;
1717 else if (typeof (byte[]) == type)
1718 return XmlConstants.QnBase64Binary;
1719 else if (typeof (XmlQualifiedName) == type)
1720 return XmlConstants.QnXmlQualifiedName;
1722 return XmlConstants.QnString;
1725 #endregion //Private Xml Serialisation