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;
611 public void WriteXml (TextWriter writer)
613 XmlTextWriter xwriter = new XmlTextWriter (writer);
614 xwriter.Formatting = Formatting.Indented;
618 public void WriteXml (XmlWriter writer)
620 WriteXml (writer, XmlWriteMode.IgnoreSchema, true);
623 public void WriteXml (string filename, XmlWriteMode mode)
625 XmlTextWriter writer = new XmlTextWriter (filename, null);
626 writer.Formatting = Formatting.Indented;
627 WriteXml (writer, mode, true);
630 public void WriteXml (Stream stream, XmlWriteMode mode)
632 XmlTextWriter writer = new XmlTextWriter (stream, null);
633 writer.Formatting = Formatting.Indented;
634 WriteXml (writer, mode, true);
637 public void WriteXml (TextWriter writer, XmlWriteMode mode)
639 XmlTextWriter xwriter = new XmlTextWriter (writer);
640 xwriter.Formatting = Formatting.Indented;
641 WriteXml (xwriter, mode, true);
644 public void WriteXml (XmlWriter writer, XmlWriteMode mode)
646 WriteXml (writer, mode, true);
649 internal void WriteXml (Stream stream, XmlWriteMode mode, bool writePI)
651 XmlTextWriter writer = new XmlTextWriter (stream, null);
652 writer.Formatting = Formatting.Indented;
653 WriteXml (writer, mode, writePI);
656 internal void WriteXml (string fileName, XmlWriteMode mode, bool writePI)
658 XmlTextWriter writer = new XmlTextWriter (fileName, null);
659 writer.Formatting = Formatting.Indented;
660 WriteXml (writer, mode, writePI);
665 internal void WriteXml (TextWriter writer, XmlWriteMode mode, bool writePI)
667 XmlTextWriter xwriter = new XmlTextWriter (writer);
668 xwriter.Formatting = Formatting.Indented;
669 WriteXml (xwriter, mode, writePI);
672 internal void WriteXml (XmlWriter writer, XmlWriteMode mode, bool writePI)
674 if (writePI && (writer.WriteState == WriteState.Start))
675 writer.WriteStartDocument (true);
677 if (mode == XmlWriteMode.DiffGram) {
679 WriteDiffGramElement(writer);
682 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
684 /*********************************************************
685 * This is a patch for interoperability with ms.net. *
686 * Because in web services the .net client expects this *
687 * atrribute even if namespace is an empty string *
688 ********************************************************/
689 if (Namespace == null || Namespace.Length == 0)
690 WriteAttributeString (writer, mode, null, null, "xmlns", Namespace);
693 if (mode == XmlWriteMode.WriteSchema) {
694 DoWriteXmlSchema (writer);
697 WriteTables (writer, mode, Tables, DataRowVersion.Default);
698 if (mode == XmlWriteMode.DiffGram) {
699 writer.WriteEndElement (); //DataSet name
700 if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
702 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
703 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
704 WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
705 writer.WriteEndElement ();
708 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
711 public void WriteXmlSchema (Stream stream)
713 XmlTextWriter writer = new XmlTextWriter (stream, null );
714 writer.Formatting = Formatting.Indented;
715 WriteXmlSchema (writer);
718 public void WriteXmlSchema (string fileName)
720 XmlTextWriter writer = new XmlTextWriter (fileName, null);
721 writer.Formatting = Formatting.Indented;
722 WriteXmlSchema (writer);
725 public void WriteXmlSchema (TextWriter writer)
727 XmlTextWriter xwriter = new XmlTextWriter (writer);
728 xwriter.Formatting = Formatting.Indented;
729 WriteXmlSchema (xwriter);
732 public void WriteXmlSchema (XmlWriter writer)
734 //Create a skeleton doc and then write the schema
735 //proper which is common to the WriteXml method in schema mode
736 writer.WriteStartDocument ();
737 DoWriteXmlSchema (writer);
739 writer.WriteEndDocument ();
742 public void ReadXmlSchema (Stream stream)
744 XmlReader reader = new XmlTextReader (stream, null);
745 ReadXmlSchema (reader);
748 public void ReadXmlSchema (string str)
750 XmlReader reader = new XmlTextReader (str);
751 ReadXmlSchema (reader);
754 public void ReadXmlSchema (TextReader treader)
756 XmlReader reader = new XmlTextReader (treader);
757 ReadXmlSchema (reader);
760 public void ReadXmlSchema (XmlReader reader)
762 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
763 SchemaMapper.Read (reader);
766 public XmlReadMode ReadXml (Stream stream)
768 return ReadXml (new XmlTextReader (stream));
771 public XmlReadMode ReadXml (string str)
773 return ReadXml (new XmlTextReader (str));
776 public XmlReadMode ReadXml (TextReader reader)
778 return ReadXml (new XmlTextReader (reader));
781 public XmlReadMode ReadXml (XmlReader r)
783 XmlDataLoader Loader = new XmlDataLoader (this);
784 // FIXME: somekinda exception?
786 return XmlReadMode.Auto; // FIXME
788 // Check if the curent element is the process instruction (PI).
789 // if it is move to next element.
790 if (r.LocalName == "xml")
793 // The document can be diffgram if :
794 // 1. The first element is diffgram.
795 if (r.LocalName == "diffgram") {
796 return ReadXml (r, XmlReadMode.DiffGram);
799 bool schemaRead = false;
800 if (r.LocalName == "schema") {
806 // If we read the schema the next element can be a diffgram
807 // that is what happen in web services soap message.
808 if (schemaRead && r.LocalName == "diffgram") {
809 return ReadXml (r, XmlReadMode.DiffGram);
812 // Get the DataSet name.
813 // if this xml is not diffgram then the first element will be the
815 string dataSetName = XmlConvert.DecodeName (r.LocalName);
816 DataSetName = dataSetName;
818 r.ReadStartElement ();
822 // After reading the dataset name there can be three scenarios:
823 // 1. The next part will be the schema of the dataset.
824 // 2. The next part will be the data of the dataset using diffgram.
825 // 3. The next part will be the data of tha dataset without diffgram.
826 // Check if the current element is the schema
827 if (r.LocalName == "schema") {
833 // check if the data was written in a diffgram mode.
834 if (r.LocalName == "diffgram") {
835 return ReadXml (r, XmlReadMode.DiffGram);
838 // If the schema has been read we should read the rest data of the dataset
839 // with ignoreschema mode.
841 ReadXml (r, XmlReadMode.IgnoreSchema, false);
842 return XmlReadMode.ReadSchema;
845 // Read the data of the dataset with inferschema.
846 return ReadXml (r, XmlReadMode.InferSchema, false);
850 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
852 return ReadXml (new XmlTextReader (stream), mode);
855 public XmlReadMode ReadXml (string str, XmlReadMode mode)
857 return ReadXml (new XmlTextReader (str), mode);
860 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
862 return ReadXml (new XmlTextReader (reader), mode);
866 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
868 // we have to initiate the reader.
869 if (reader.ReadState == ReadState.Initial)
872 // Check if the curent element is the process instruction (PI).
873 // if it is move to next element.
874 if (reader.LocalName == "xml")
875 reader.MoveToContent();
877 XmlReadMode Result = XmlReadMode.Auto;
879 if (mode == XmlReadMode.DiffGram) {
880 if (reader.LocalName != "diffgram"){
881 reader.MoveToContent ();
882 reader.ReadStartElement (); // <DataSet>
884 reader.MoveToContent ();
885 if (reader.LocalName == "schema")
886 ReadXmlSchema (reader);
888 reader.MoveToContent ();
890 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
891 DiffLoader.Load (reader);
892 Result = XmlReadMode.DiffGram;
895 Result = ReadXml(reader, mode, true);
900 private XmlReadMode ReadXml (XmlReader r, XmlReadMode mode, bool readDataSet) {
903 string dataSetName = XmlConvert.DecodeName (r.LocalName);
904 DataSetName = dataSetName;
905 // get the Namespace of the DataSet.
906 string tmp = r.GetAttribute("xmlns");
910 r.ReadStartElement ();
914 XmlDataLoader Loader = new XmlDataLoader (this);
915 return Loader.LoadData (r, mode);
918 #endregion // Public Methods
920 #region Public Events
922 [DataCategory ("Action")]
923 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
924 public event MergeFailedEventHandler MergeFailed;
926 #endregion // Public Events
934 #endregion Destructors
936 #region IListSource methods
937 IList IListSource.GetList ()
939 return DefaultViewManager;
942 bool IListSource.ContainsListCollection {
947 #endregion IListSource methods
949 #region ISupportInitialize methods
950 public void BeginInit ()
954 public void EndInit ()
959 #region ISerializable
960 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
962 throw new NotImplementedException ();
966 #region Protected Methods
967 protected void GetSerializationData (SerializationInfo info, StreamingContext context)
969 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
970 if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s)));
974 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
979 protected virtual void ReadXmlSerializable (XmlReader reader)
981 ReadXml (reader, XmlReadMode.DiffGram); // FIXME
984 void IXmlSerializable.ReadXml (XmlReader reader)
987 ReadXmlSerializable(reader);
989 // the XmlSerializationReader does this lines!!!
990 //reader.MoveToContent ();
991 //reader.ReadEndElement (); // </DataSet>
994 void IXmlSerializable.WriteXml (XmlWriter writer)
996 DoWriteXmlSchema (writer);
997 WriteXml (writer, XmlWriteMode.DiffGram, true);
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 return o.ToString ();
1076 private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
1078 //Write out each table in order, providing it is not
1079 //part of another table structure via a nested parent relationship
1080 foreach (DataTable table in tableCollection) {
1081 bool isTopLevel = true;
1082 foreach (DataRelation rel in table.ParentRelations) {
1090 WriteTable ( writer, table, mode, version);
1095 private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
1097 DataRow[] rows = new DataRow [table.Rows.Count];
1098 table.Rows.CopyTo (rows, 0);
1099 WriteTable (writer, rows, mode, version);
1102 private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version)
1104 //The columns can be attributes, hidden, elements, or simple content
1105 //There can be 0-1 simple content cols or 0-* elements
1106 System.Collections.ArrayList atts;
1107 System.Collections.ArrayList elements;
1108 DataColumn simple = null;
1110 if (rows.Length == 0) return;
1111 DataTable table = rows[0].Table;
1112 SplitColumns (table, out atts, out elements, out simple);
1113 //sort out the namespacing
1114 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
1116 foreach (DataRow row in rows) {
1117 if (!row.HasVersion(version) ||
1118 (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
1119 && version == DataRowVersion.Original))
1122 // First check are all the rows null. If they are we just write empty element
1123 bool AllNulls = true;
1124 foreach (DataColumn dc in table.Columns) {
1126 if (row [dc.ColumnName, version] != DBNull.Value) {
1132 // If all of the columns were null, we have to write empty element
1134 writer.WriteElementString (table.TableName, "");
1138 WriteTableElement (writer, mode, table, row, version);
1140 foreach (DataColumn col in atts) {
1141 WriteColumnAsAttribute (writer, mode, col, row, version);
1144 if (simple != null) {
1145 writer.WriteString (WriteObjectXml (row[simple, version]));
1148 foreach (DataColumn col in elements) {
1149 WriteColumnAsElement (writer, mode, nspc, col, row, version);
1153 foreach (DataRelation relation in table.ChildRelations) {
1154 if (relation.Nested) {
1155 WriteTable (writer, row.GetChildRows (relation), mode, version);
1159 writer.WriteEndElement ();
1164 private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version)
1166 string colnspc = nspc;
1167 object rowObject = row [col, version];
1169 if (rowObject == null || rowObject == DBNull.Value)
1172 if (col.Namespace != null) {
1173 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 if (nspc == null || nspc == "") {
1211 writer.WriteStartElement (name);
1213 else if (prefix != null) {
1214 writer.WriteStartElement (prefix, name, nspc);
1217 writer.WriteStartElement (writer.LookupPrefix (nspc), name, nspc);
1221 private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
1224 case XmlWriteMode.WriteSchema:
1225 writer.WriteAttributeString (prefix, name, nspc);
1227 case XmlWriteMode.DiffGram:
1228 writer.WriteAttributeString (prefix, name, nspc,stringValue);
1231 writer.WriteAttributeString (name, stringValue);
1236 internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
1238 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
1240 if (mode == XmlWriteMode.DiffGram) {
1241 SetTableRowsID (table);
1242 WriteDiffGramElement (writer);
1245 WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
1247 WriteTable (writer, table, mode, DataRowVersion.Default);
1249 if (mode == XmlWriteMode.DiffGram) {
1250 writer.WriteEndElement (); //DataSet name
1251 if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
1253 DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
1254 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
1255 WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
1256 writer.WriteEndElement ();
1259 writer.WriteEndElement (); // DataSet name or diffgr:diffgram
1262 XmlSchema IXmlSerializable.GetSchema ()
1264 return BuildSchema ();
1267 XmlSchema BuildSchema ()
1269 return BuildSchema (Tables, Relations);
1272 internal XmlSchema BuildSchema (DataTableCollection tables, DataRelationCollection relations)
1274 string constraintPrefix = "";
1275 XmlSchema schema = new XmlSchema ();
1277 schema.Namespaces.Add("xs", XmlSchema.Namespace);
1278 schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1280 if (Namespace != "" && Namespace != null) {
1281 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
1282 schema.ElementFormDefault = XmlSchemaForm.Qualified;
1283 schema.TargetNamespace = Namespace;
1284 schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace);
1285 constraintPrefix = XmlConstants.TnsPrefix + ":";
1288 // set the schema id
1289 schema.Id = DataSetName;
1290 XmlDocument doc = new XmlDocument ();
1291 XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns");
1292 xmlnsAttr.Value = Namespace;
1294 schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr};
1296 XmlSchemaElement elem = new XmlSchemaElement ();
1297 elem.Name = XmlConvert.EncodeName (DataSetName);
1299 XmlAttribute[] atts = new XmlAttribute [2];
1300 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
1301 atts[0].Value = "true";
1303 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
1304 atts[1].Value = locale.Name;
1305 elem.UnhandledAttributes = atts;
1307 schema.Items.Add (elem);
1309 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1310 elem.SchemaType = complex;
1312 XmlSchemaChoice choice = new XmlSchemaChoice ();
1313 complex.Particle = choice;
1314 choice.MaxOccursString = XmlConstants.Unbounded;
1316 //Write out schema for each table in order
1317 foreach (DataTable table in tables) {
1318 bool isTopLevel = true;
1319 foreach (DataRelation rel in table.ParentRelations) {
1327 choice.Items.Add (GetTableSchema (doc, table));
1331 AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
1335 // Add all constraints in all tables to the schema.
1336 private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
1338 // first add all unique constraints.
1339 Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
1340 // Add all foriegn key constraints.
1341 AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
1344 // Add unique constaraints to the schema.
1345 // return hashtable with the names of all XmlSchemaUnique elements we created.
1346 private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
1348 XmlDocument doc = new XmlDocument();
1349 Hashtable uniqueNames = new Hashtable();
1350 foreach (DataTable table in tables) {
1352 foreach (Constraint constaint in table.Constraints) {
1354 if (constaint is UniqueConstraint) {
1355 ArrayList attrs = new ArrayList ();
1356 XmlAttribute attrib;
1357 UniqueConstraint uqConst = (UniqueConstraint)constaint;
1358 XmlSchemaUnique uniq = new XmlSchemaUnique ();
1360 // if column of the constraint is hidden do not write the constraint.
1361 bool isHidden = false;
1362 foreach (DataColumn column in uqConst.Columns) {
1363 if (column.ColumnMapping == MappingType.Hidden) {
1372 // if constaraint name do not exist in the hashtable we can use it.
1373 if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
1374 uniq.Name = uqConst.ConstraintName;
1376 // generate new constraint name for the XmlSchemaUnique element.
1378 uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
1379 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
1380 attrib.Value = uqConst.ConstraintName;
1383 if (uqConst.IsPrimaryKey) {
1384 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
1385 attrib.Value = "true";
1389 uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1391 uniq.Selector = new XmlSchemaXPath();
1392 uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
1393 XmlSchemaXPath field;
1394 foreach (DataColumn column in uqConst.Columns) {
1395 field = new XmlSchemaXPath();
1396 field.XPath = constraintPrefix+column.ColumnName;
1397 uniq.Fields.Add(field);
1400 elem.Constraints.Add (uniq);
1401 uniqueNames.Add (uniq.Name, null);
1408 // Add the foriegn keys to the schema.
1409 private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
1411 if (relations == null) return;
1413 XmlDocument doc = new XmlDocument();
1414 foreach (DataRelation rel in relations) {
1416 if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
1419 ArrayList attrs = new ArrayList ();
1420 XmlAttribute attrib;
1421 XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
1422 keyRef.Name = rel.RelationName;
1423 ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
1424 UniqueConstraint uqConst = rel.ParentKeyConstraint;
1426 string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
1427 // first try to find the concatenated name. If we didn't find it - use constraint name.
1428 if (uniqueNames.ContainsKey (concatName)) {
1429 keyRef.Refer = new XmlQualifiedName(concatName);
1432 keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
1436 attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
1437 attrib.Value = "true";
1441 keyRef.Selector = new XmlSchemaXPath();
1442 keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
1443 XmlSchemaXPath field;
1444 foreach (DataColumn column in rel.ChildColumns) {
1445 field = new XmlSchemaXPath();
1446 field.XPath = constraintPrefix+column.ColumnName;
1447 keyRef.Fields.Add(field);
1449 keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
1450 elem.Constraints.Add (keyRef);
1454 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1460 SplitColumns (table, out atts, out elements, out simple);
1462 XmlSchemaElement elem = new XmlSchemaElement ();
1463 elem.Name = table.TableName;
1465 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1466 elem.SchemaType = complex;
1468 //TODO - what about the simple content?
1469 if (simple != null) {
1470 // add simpleContent
1471 XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
1472 complex.ContentModel = simpleContent;
1474 // add column name attribute
1475 XmlAttribute[] xlmAttrs = new XmlAttribute [2];
1476 xlmAttrs[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ColumnName, XmlConstants.MsdataNamespace);
1477 xlmAttrs[0].Value = simple.ColumnName;
1479 // add ordinal attribute
1480 xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace);
1481 xlmAttrs[1].Value = simple.Ordinal.ToString();
1482 simpleContent.UnhandledAttributes = xlmAttrs;
1486 XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
1487 simpleContent.Content = extension;
1488 extension.BaseTypeName = MapType (simple.DataType);
1492 //A sequence of element types or a simple content node
1494 XmlSchemaSequence seq = new XmlSchemaSequence ();
1495 complex.Particle = seq;
1497 foreach (DataColumn col in elements) {
1499 // Add element for the column.
1500 XmlSchemaElement colElem = new XmlSchemaElement ();
1501 ArrayList xattrs = new ArrayList();
1503 colElem.Name = col.ColumnName;
1505 if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
1506 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1507 xattr.Value = col.Caption;
1511 if (col.AutoIncrement == true) {
1512 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrement, XmlConstants.MsdataNamespace);
1513 xattr.Value = "true";
1517 if (col.AutoIncrementSeed != 0) {
1518 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace);
1519 xattr.Value = col.AutoIncrementSeed.ToString();
1523 if (col.DefaultValue.ToString () != String.Empty)
1524 colElem.DefaultValue = col.DefaultValue.ToString ();
1526 if (col.MaxLength < 0)
1527 colElem.SchemaTypeName = MapType (col.DataType);
1529 if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string)
1530 && col.DataType != typeof (char)) {
1531 xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace);
1532 xattr.Value = col.DataType.ToString();
1536 if (col.AllowDBNull) {
1537 colElem.MinOccurs = 0;
1540 //writer.WriteAttributeString (XmlConstants.MsdataPrefix,
1541 // XmlConstants.Ordinal,
1542 // XmlConstants.MsdataNamespace,
1543 // col.Ordinal.ToString ());
1545 // Write SimpleType if column have MaxLength
1546 if (col.MaxLength > -1) {
1547 colElem.SchemaType = GetTableSimpleType (doc, col);
1550 colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
1551 seq.Items.Add (colElem);
1554 foreach (DataRelation rel in table.ChildRelations) {
1556 seq.Items.Add(GetTableSchema (doc, rel.ChildTable));
1561 //Then a list of attributes
1562 foreach (DataColumn col in atts) {
1563 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1564 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1565 att.Name = col.ColumnName;
1566 att.Form = XmlSchemaForm.Unqualified;
1567 att.SchemaTypeName = MapType (col.DataType);
1568 complex.Attributes.Add (att);
1574 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1577 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1580 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1581 restriction.BaseTypeName = MapType (col.DataType);
1584 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1585 max.Value = XmlConvert.ToString (col.MaxLength);
1586 restriction.Facets.Add (max);
1588 simple.Content = restriction;
1592 private void DoWriteXmlSchema (XmlWriter writer)
1594 BuildSchema ().Write (writer);
1598 /// Helper function to split columns into attributes elements and simple
1601 private void SplitColumns (DataTable table,
1603 out ArrayList elements,
1604 out DataColumn simple)
1606 //The columns can be attributes, hidden, elements, or simple content
1607 //There can be 0-1 simple content cols or 0-* elements
1608 atts = new System.Collections.ArrayList ();
1609 elements = new System.Collections.ArrayList ();
1612 //Sort out the columns
1613 foreach (DataColumn col in table.Columns) {
1614 switch (col.ColumnMapping) {
1615 case MappingType.Attribute:
1618 case MappingType.Element:
1621 case MappingType.SimpleContent:
1622 if (simple != null) {
1623 throw new System.InvalidOperationException ("There may only be one simple content element");
1628 //ignore Hidden elements
1634 private void WriteDiffGramElement(XmlWriter writer)
1636 WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
1637 WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
1640 private void SetRowsID()
1642 foreach (DataTable Table in Tables)
1643 SetTableRowsID (Table);
1646 private void SetTableRowsID (DataTable Table)
1649 foreach (DataRow Row in Table.Rows) {
1650 Row.XmlRowID = dataRowID;
1656 private XmlQualifiedName MapType (Type type)
1658 switch (Type.GetTypeCode (type)) {
1659 case TypeCode.String: return XmlConstants.QnString;
1660 case TypeCode.Int16: return XmlConstants.QnShort;
1661 case TypeCode.Int32: return XmlConstants.QnInt;
1662 case TypeCode.Int64: return XmlConstants.QnLong;
1663 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1664 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1665 //case TypeCode.Char: return XmlConstants.QnChar;
1666 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1667 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1668 case TypeCode.Double: return XmlConstants.QnDouble;
1669 case TypeCode.SByte: return XmlConstants.QnSbyte;
1670 case TypeCode.Single: return XmlConstants.QnFloat;
1671 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1672 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1673 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1676 if (typeof (TimeSpan) == type)
1677 return XmlConstants.QnDuration;
1678 else if (typeof (System.Uri) == type)
1679 return XmlConstants.QnUri;
1680 else if (typeof (byte[]) == type)
1681 return XmlConstants.QnBase64Binary;
1682 else if (typeof (XmlQualifiedName) == type)
1683 return XmlConstants.QnXmlQualifiedName;
1685 return XmlConstants.QnString;
1688 #endregion //Private Xml Serialisation