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
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 {
30 /// an in-memory cache of data
34 [DefaultProperty ("DataSetName")]
36 public class DataSet : MarshalByValueComponent, IListSource,
37 ISupportInitialize, ISerializable, IXmlSerializable {
38 private string dataSetName;
39 private string _namespace = "";
40 private string prefix;
41 private bool caseSensitive;
42 private bool enforceConstraints = true;
43 private DataTableCollection tableCollection;
44 private DataRelationCollection relationCollection;
45 private PropertyCollection properties;
46 private DataViewManager defaultView;
47 private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
51 public DataSet() : this ("NewDataSet") {
54 public DataSet(string name) {
56 tableCollection = new DataTableCollection (this);
57 relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
58 properties = new PropertyCollection();
62 protected DataSet(SerializationInfo info, StreamingContext context) : this () {
63 throw new NotImplementedException ();
66 #endregion // Constructors
68 #region Public Properties
70 [DataCategory ("Data")]
71 [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
72 [DefaultValue (false)]
73 public bool CaseSensitive {
74 get { return caseSensitive; }
76 foreach (DataTable T in Tables) {
77 if (T.VirginCaseSensitive)
78 T.CaseSensitive = value;
81 caseSensitive = value;
85 [DataCategory ("Data")]
86 [DataSysDescription ("The name of this DataSet.")]
88 public string DataSetName {
89 get { return dataSetName; }
90 set { dataSetName = value; }
93 [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
95 public DataViewManager DefaultViewManager {
97 if (defaultView == null)
98 defaultView = new DataViewManager (this);
103 [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
104 [DefaultValue (true)]
105 public bool EnforceConstraints {
106 get { return enforceConstraints; }
107 set { enforceConstraints = value; }
111 [DataCategory ("Data")]
112 [DataSysDescription ("The collection that holds custom user information.")]
113 public PropertyCollection ExtendedProperties {
114 get { return properties; }
118 [DataSysDescription ("Indicates that the DataSet has errors.")]
119 public bool HasErrors {
122 throw new NotImplementedException ();
126 [DataCategory ("Data")]
127 [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
128 public CultureInfo Locale {
133 if (locale == null || !locale.Equals(value)) {
134 // TODO: check if the new locale is valid
135 // TODO: update locale of all tables
141 public void Merge (DataRow[] rows)
143 Merge (rows, false, MissingSchemaAction.Add);
146 public void Merge (DataSet dataSet)
148 Merge (dataSet, false, MissingSchemaAction.Add);
151 public void Merge (DataTable table)
153 Merge (table, false, MissingSchemaAction.Add);
156 public void Merge (DataSet dataSet, bool preserveChanges)
158 Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
162 public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
165 throw new ArgumentNullException("rows");
166 if(!IsLegalSchemaAction(missingSchemaAction))
167 throw new ArgumentOutOfRangeException("missingSchemaAction");
169 MergeManager.Merge(this, rows, preserveChanges, missingSchemaAction);
173 public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
176 throw new ArgumentNullException("dataSet");
177 if(!IsLegalSchemaAction(missingSchemaAction))
178 throw new ArgumentOutOfRangeException("missingSchemaAction");
180 MergeManager.Merge(this, dataSet, preserveChanges, missingSchemaAction);
184 public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
187 throw new ArgumentNullException("table");
188 if(!IsLegalSchemaAction(missingSchemaAction))
189 throw new ArgumentOutOfRangeException("missingSchemaAction");
191 MergeManager.Merge(this, table, preserveChanges, missingSchemaAction);
194 private static bool IsLegalSchemaAction(MissingSchemaAction missingSchemaAction)
196 if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
197 || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
202 [DataCategory ("Data")]
203 [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
205 public string Namespace {
207 get { return _namespace; }
210 //TODO - trigger an event if this happens?
215 [DataCategory ("Data")]
216 [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
218 public string Prefix {
220 get { return prefix; }
223 //TODO - trigger an event if this happens?
228 [DataCategory ("Data")]
229 [DataSysDescription ("The collection that holds the relations for this DatSet.")]
230 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
231 public DataRelationCollection Relations {
233 return relationCollection;
238 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
239 public override ISite Site {
242 throw new NotImplementedException ();
247 throw new NotImplementedException ();
251 [DataCategory ("Data")]
252 [DataSysDescription ("The collection that holds the tables for this DataSet.")]
253 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
254 public DataTableCollection Tables {
255 get { return tableCollection; }
258 #endregion // Public Properties
260 #region Public Methods
263 public void AcceptChanges()
265 foreach (DataTable tempTable in tableCollection)
266 tempTable.AcceptChanges ();
271 // TODO: if currently bound to a XmlDataDocument
272 // throw a NotSupportedException
273 for (int t = 0; t < tableCollection.Count; t++) {
274 tableCollection[t].Clear ();
278 public virtual DataSet Clone()
280 DataSet Copy = new DataSet ();
281 CopyProperties (Copy);
283 foreach (DataTable Table in Tables) {
284 Copy.Tables.Add (Table.Clone ());
290 // Copies both the structure and data for this DataSet.
291 public DataSet Copy()
293 DataSet Copy = new DataSet ();
294 CopyProperties (Copy);
296 // Copy DatSet's tables
297 foreach (DataTable Table in Tables) {
298 Copy.Tables.Add (Table.Copy ());
305 private void CopyProperties (DataSet Copy)
307 Copy.CaseSensitive = CaseSensitive;
308 //Copy.Container = Container
309 Copy.DataSetName = DataSetName;
310 //Copy.DefaultViewManager
312 Copy.EnforceConstraints = EnforceConstraints;
313 //Copy.ExtendedProperties
315 //Copy.Locale = Locale;
316 Copy.Namespace = Namespace;
317 Copy.Prefix = Prefix;
318 //Copy.Relations = Relations;
323 public DataSet GetChanges()
325 return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
329 public DataSet GetChanges(DataRowState rowStates)
331 if(!HasChanges(rowStates))
334 DataSet copySet = Clone();
335 IEnumerator tableEnumerator = Tables.GetEnumerator();
338 while (tableEnumerator.MoveNext())
340 origTable = (DataTable)tableEnumerator.Current;
341 copyTable = copySet.Tables[origTable.TableName];
343 IEnumerator rowEnumerator = origTable.Rows.GetEnumerator();
344 while (rowEnumerator.MoveNext())
346 DataRow row = (DataRow)rowEnumerator.Current;
347 if (row.IsRowChanged(rowStates))
349 DataRow newRow = copyTable.NewRow();
350 copyTable.Rows.Add(newRow);
351 row.CopyValuesToRow(newRow);
359 public string GetXml()
361 StringWriter Writer = new StringWriter ();
362 WriteXml (Writer, XmlWriteMode.IgnoreSchema);
363 return Writer.ToString ();
366 public string GetXmlSchema()
368 StringWriter Writer = new StringWriter ();
369 WriteXmlSchema (Writer);
370 return Writer.ToString ();
374 public bool HasChanges()
376 return HasChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
380 public bool HasChanges(DataRowState rowState)
382 if(((int)rowState & 0xffffffe0) != 0)
383 throw new ArgumentOutOfRangeException("rowState");
385 DataTableCollection tableCollection = Tables;
387 DataRowCollection rowCollection;
389 for (int i = 0; i < tableCollection.Count; i++)
391 table = tableCollection[i];
392 rowCollection = table.Rows;
393 for (int j = 0; j < rowCollection.Count; j++)
395 row = rowCollection[j];
396 if((row.RowState & rowState) != 0)
405 public void InferXmlSchema(XmlReader reader, string[] nsArray)
409 public void InferXmlSchema(Stream stream, string[] nsArray)
411 InferXmlSchema (new XmlTextReader(stream), nsArray);
414 public void InferXmlSchema(TextReader reader, string[] nsArray)
416 InferXmlSchema (new XmlTextReader(reader), nsArray);
419 public void InferXmlSchema(string fileName, string[] nsArray)
421 XmlTextReader reader = new XmlTextReader(fileName);
423 InferXmlSchema (reader, nsArray);
429 public virtual void RejectChanges()
431 throw new NotImplementedException();
434 public virtual void Reset()
436 throw new NotImplementedException ();
439 public void WriteXml(Stream stream)
441 XmlWriter writer = new XmlTextWriter(stream, null );
447 /// Writes the current data for the DataSet to the specified file.
449 /// <param name="filename">Fully qualified filename to write to</param>
450 public void WriteXml(string fileName)
452 XmlWriter writer = new XmlTextWriter(fileName, null );
459 public void WriteXml(TextWriter writer)
461 XmlWriter xwriter = new XmlTextWriter(writer );
466 public void WriteXml(XmlWriter writer)
468 WriteXml( writer, XmlWriteMode.IgnoreSchema );
471 public void WriteXml(Stream stream, XmlWriteMode mode)
473 XmlWriter writer = new XmlTextWriter(stream, null );
475 WriteXml( writer, mode );
478 public void WriteXml(string fileName, XmlWriteMode mode)
480 XmlWriter writer = new XmlTextWriter(fileName, null );
482 WriteXml( writer, mode );
487 public void WriteXml(TextWriter writer, XmlWriteMode mode)
489 XmlWriter xwriter = new XmlTextWriter(writer);
491 WriteXml( xwriter, mode );
494 public void WriteXml(XmlWriter writer, XmlWriteMode mode)
496 if (writer.WriteState == WriteState.Start)
497 writer.WriteStartDocument (true);
499 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
500 WriteStartElement( writer, mode, Namespace, Prefix, DataSetName );
502 if( mode == XmlWriteMode.WriteSchema )
504 DoWriteXmlSchema( writer );
507 //Write out each table in order, providing it is not
508 //part of another table structure via a nested parent relationship
509 foreach( DataTable table in Tables )
511 bool isTopLevel = true;
512 foreach( DataRelation rel in table.ParentRelations )
523 WriteTable( writer, table, mode );
527 writer.WriteEndElement();
530 public void WriteXmlSchema(Stream stream)
532 XmlWriter writer = new XmlTextWriter(stream, null );
534 WriteXmlSchema( writer );
537 public void WriteXmlSchema(string fileName)
539 XmlWriter writer = new XmlTextWriter( fileName, null );
541 WriteXmlSchema( writer );
544 public void WriteXmlSchema(TextWriter writer)
546 XmlWriter xwriter = new XmlTextWriter( writer );
548 WriteXmlSchema( xwriter );
551 public void WriteXmlSchema(XmlWriter writer)
553 ((XmlTextWriter)writer).Formatting = Formatting.Indented;
554 //Create a skeleton doc and then write the schema
555 //proper which is common to the WriteXml method in schema mode
556 writer.WriteStartDocument();
558 DoWriteXmlSchema( writer );
560 writer.WriteEndDocument();
563 public void ReadXmlSchema(Stream stream)
565 XmlReader reader = new XmlTextReader( stream, null );
566 ReadXmlSchema( reader);
569 public void ReadXmlSchema(string str)
571 XmlReader reader = new XmlTextReader( str );
572 ReadXmlSchema( reader );
575 public void ReadXmlSchema(TextReader treader)
577 XmlReader reader = new XmlTextReader( treader );
578 ReadXmlSchema( reader );
581 public void ReadXmlSchema(XmlReader reader)
583 XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
584 SchemaMapper.Read (reader);
587 public XmlReadMode ReadXml (Stream stream)
589 return ReadXml (new XmlTextReader (stream));
592 public XmlReadMode ReadXml (string str)
594 return ReadXml (new XmlTextReader (str));
597 public XmlReadMode ReadXml (TextReader reader)
599 return ReadXml (new XmlTextReader (reader));
602 public XmlReadMode ReadXml (XmlReader r)
604 XmlDataLoader Loader = new XmlDataLoader (this);
605 // FIXME: somekinda exception?
607 return XmlReadMode.Auto; // FIXME
610 * If document is diffgram we will use diffgram
612 if (r.LocalName == "diffgram")
613 return ReadXml (r, XmlReadMode.DiffGram);
616 * If we already have a schema, or the document
617 * contains an in-line schema, sets XmlReadMode to ReadSchema.
620 // FIXME: is this always true: "if we have tables we have to have schema also"
621 if (Tables.Count > 0)
622 return ReadXml (r, XmlReadMode.ReadSchema);
625 * If we dont have a schema yet and document
626 * contains no inline-schema mode is XmlReadMode.InferSchema
629 return ReadXml (r, XmlReadMode.InferSchema);
633 public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
635 return ReadXml (new XmlTextReader (stream), mode);
638 public XmlReadMode ReadXml (string str, XmlReadMode mode)
640 return ReadXml (new XmlTextReader (str), mode);
643 public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
645 return ReadXml (new XmlTextReader (reader), mode);
649 public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
651 XmlReadMode Result = XmlReadMode.Auto;
653 if (mode == XmlReadMode.DiffGram) {
654 XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
655 DiffLoader.Load (reader);
656 Result = XmlReadMode.DiffGram;
659 XmlDataLoader Loader = new XmlDataLoader (this);
660 Result = Loader.LoadData (reader, mode);
666 #endregion // Public Methods
668 #region Public Events
670 [DataCategory ("Action")]
671 [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
672 public event MergeFailedEventHandler MergeFailed;
674 #endregion // Public Events
682 #endregion Destructors
684 #region IListSource methods
685 IList IListSource.GetList ()
687 return DefaultViewManager;
690 bool IListSource.ContainsListCollection {
695 #endregion IListSource methods
697 #region ISupportInitialize methods
698 public void BeginInit ()
700 throw new NotImplementedException ();
703 public void EndInit ()
705 throw new NotImplementedException ();
709 #region ISerializable
710 void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
712 throw new NotImplementedException ();
716 #region Protected Methods
717 protected void GetSerializationData(SerializationInfo info, StreamingContext context)
719 string s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
720 if (s != null) ReadXmlSerializable (new XmlTextReader(new StringReader(s)));
724 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable()
726 return BuildSchema ();
729 protected virtual void ReadXmlSerializable(XmlReader reader)
731 ReadXml(reader, XmlReadMode.DiffGram); // FIXME
734 void IXmlSerializable.ReadXml(XmlReader reader)
736 reader.MoveToContent ();
737 reader.ReadStartElement (); // <DataSet>
739 reader.MoveToContent ();
740 ReadXmlSchema (reader);
742 reader.MoveToContent ();
743 ReadXml(reader, XmlReadMode.IgnoreSchema);
745 reader.MoveToContent ();
746 reader.ReadEndElement (); // </DataSet>
749 void IXmlSerializable.WriteXml(XmlWriter writer)
751 DoWriteXmlSchema (writer);
752 WriteXml(writer, XmlWriteMode.IgnoreSchema);
755 protected virtual bool ShouldSerializeRelations ()
760 protected virtual bool ShouldSerializeTables ()
766 protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
771 protected virtual void OnRemoveRelation (DataRelation relation)
776 protected virtual void OnRemoveTable (DataTable table)
780 protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
782 if (MergeFailed != null)
783 MergeFailed(this, e);
787 protected internal void RaisePropertyChanging (string name)
792 #region Private Xml Serialisation
794 private string WriteObjectXml( object o ) {
795 switch (Type.GetTypeCode (o.GetType ())) {
796 case TypeCode.Boolean:
797 return XmlConvert.ToString ((Boolean) o);
799 return XmlConvert.ToString ((Byte) o);
801 return XmlConvert.ToString ((Char) o);
802 case TypeCode.DateTime:
803 return XmlConvert.ToString ((DateTime) o);
804 case TypeCode.Decimal:
805 return XmlConvert.ToString ((Decimal) o);
806 case TypeCode.Double:
807 return XmlConvert.ToString ((Double) o);
809 return XmlConvert.ToString ((Int16) o);
811 return XmlConvert.ToString ((Int32) o);
813 return XmlConvert.ToString ((Int64) o);
815 return XmlConvert.ToString ((SByte) o);
816 case TypeCode.Single:
817 return XmlConvert.ToString ((Single) o);
818 case TypeCode.UInt16:
819 return XmlConvert.ToString ((UInt16) o);
820 case TypeCode.UInt32:
821 return XmlConvert.ToString ((UInt32) o);
822 case TypeCode.UInt64:
823 return XmlConvert.ToString ((UInt64) o);
825 if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
826 if (o is Guid) return XmlConvert.ToString ((Guid) o);
830 private void WriteTable( XmlWriter writer, DataTable table, XmlWriteMode mode )
832 DataRow[] rows = new DataRow [table.Rows.Count];
833 table.Rows.CopyTo (rows, 0);
834 WriteTable (writer, rows, mode);
837 private void WriteTable( XmlWriter writer, DataRow[] rows, XmlWriteMode mode )
839 //The columns can be attributes, hidden, elements, or simple content
840 //There can be 0-1 simple content cols or 0-* elements
841 System.Collections.ArrayList atts;
842 System.Collections.ArrayList elements;
843 DataColumn simple = null;
845 if (rows.Length == 0) return;
846 DataTable table = rows[0].Table;
847 SplitColumns( table, out atts, out elements, out simple );
849 foreach( DataRow row in rows )
851 //sort out the namespacing
852 string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
854 // First check are all the rows null. If they are we just write empty element
855 bool AllNulls = true;
856 foreach (DataColumn dc in table.Columns) {
858 if (row [dc.ColumnName] != DBNull.Value) {
864 // If all of the columns were null, we have to write empty element
866 writer.WriteElementString (table.TableName, "");
870 WriteStartElement( writer, mode, nspc, table.Prefix, table.TableName );
872 foreach( DataColumn col in atts )
874 WriteAttributeString( writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col].ToString() );
879 writer.WriteString( WriteObjectXml(row[simple]) );
883 foreach( DataColumn col in elements )
885 string colnspc = nspc;
886 object rowObject = row [col];
888 if (rowObject == null || rowObject == DBNull.Value)
891 if( col.Namespace != null )
893 colnspc = col.Namespace;
896 //TODO check if I can get away with write element string
897 WriteStartElement( writer, mode, colnspc, col.Prefix, col.ColumnName );
898 writer.WriteString( WriteObjectXml(rowObject) );
899 writer.WriteEndElement();
903 foreach (DataRelation relation in table.ChildRelations) {
904 if (relation.Nested) {
905 WriteTable (writer, row.GetChildRows(relation), mode);
909 writer.WriteEndElement();
914 private void WriteStartElement( XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name )
918 case XmlWriteMode.WriteSchema:
919 if( nspc == null || nspc == "" )
921 writer.WriteStartElement( name );
923 else if( prefix != null )
925 writer.WriteStartElement(prefix, name, nspc );
929 writer.WriteStartElement( writer.LookupPrefix( nspc ), name, nspc );
932 case XmlWriteMode.DiffGram:
933 throw new NotImplementedException();
935 writer.WriteStartElement(name );
940 private void WriteAttributeString( XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue )
944 case XmlWriteMode.WriteSchema:
945 writer.WriteAttributeString(prefix, name, nspc );
947 case XmlWriteMode.DiffGram:
948 throw new NotImplementedException();
950 writer.WriteAttributeString(name, stringValue );
955 XmlSchema IXmlSerializable.GetSchema()
957 return BuildSchema ();
960 XmlSchema BuildSchema()
962 XmlSchema schema = new XmlSchema ();
963 schema.AttributeFormDefault = XmlSchemaForm.Qualified;
965 XmlSchemaElement elem = new XmlSchemaElement ();
966 elem.Name = DataSetName;
968 XmlDocument doc = new XmlDocument ();
970 XmlAttribute[] atts = new XmlAttribute [2];
971 atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace);
972 atts[0].Value = "true";
974 atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace);
975 atts[1].Value = locale.Name;
976 elem.UnhandledAttributes = atts;
978 schema.Items.Add (elem);
980 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
981 elem.SchemaType = complex;
983 XmlSchemaChoice choice = new XmlSchemaChoice ();
984 complex.Particle = choice;
985 choice.MaxOccursString = XmlConstants.Unbounded;
987 //Write out schema for each table in order, providing it is not
988 //part of another table structure via a nested parent relationship
989 foreach( DataTable table in Tables )
991 bool isTopLevel = true;
992 foreach( DataRelation rel in table.ParentRelations )
1003 choice.Items.Add (GetTableSchema (doc, table));
1007 //TODO - now add in the relationships as key and unique constraints etc
1012 private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table)
1018 SplitColumns (table, out atts, out elements, out simple);
1020 XmlSchemaElement elem = new XmlSchemaElement ();
1021 elem.Name = table.TableName;
1023 XmlSchemaComplexType complex = new XmlSchemaComplexType ();
1024 elem.SchemaType = complex;
1026 //TODO - what about the simple content?
1027 if( elements.Count == 0 )
1032 //A sequence of element types or a simple content node
1034 XmlSchemaSequence seq = new XmlSchemaSequence ();
1035 complex.Particle = seq;
1037 foreach( DataColumn col in elements )
1039 //<xs:element name=ColumnName type=MappedType Ordinal=index>
1040 XmlSchemaElement colElem = new XmlSchemaElement ();
1041 colElem.Name = col.ColumnName;
1043 if (col.ColumnName != col.Caption && col.Caption != string.Empty)
1045 XmlAttribute[] xatts = new XmlAttribute[1];
1046 xatts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Caption, XmlConstants.MsdataNamespace);
1047 xatts[0].Value = col.Caption;
1048 colElem.UnhandledAttributes = xatts;
1051 if (col.DefaultValue.ToString () != string.Empty)
1052 colElem.DefaultValue = col.DefaultValue.ToString ();
1054 colElem.SchemaTypeName = MapType (col.DataType);
1056 if( col.AllowDBNull )
1058 colElem.MinOccurs = 0;
1061 //writer.WriteAttributeString( XmlConstants.MsdataPrefix,
1062 // XmlConstants.Ordinal,
1063 // XmlConstants.MsdataNamespace,
1064 // col.Ordinal.ToString() );
1066 // Write SimpleType if column have MaxLength
1067 if (col.MaxLength > -1)
\r
1069 colElem.SchemaType = GetTableSimpleType (doc, col);
1072 seq.Items.Add (colElem);
1076 //Then a list of attributes
1077 foreach( DataColumn col in atts )
1079 //<xs:attribute name=col.ColumnName form="unqualified" type=MappedType/>
1080 XmlSchemaAttribute att = new XmlSchemaAttribute ();
1081 att.Name = col.ColumnName;
1082 att.Form = XmlSchemaForm.Unqualified;
1083 att.SchemaTypeName = MapType (col.DataType);
1084 complex.Attributes.Add (att);
1089 private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col)
1092 XmlSchemaSimpleType simple = new XmlSchemaSimpleType ();
1095 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction ();
1096 restriction.BaseTypeName = MapType (col.DataType);
1099 XmlSchemaMaxLengthFacet max = new XmlSchemaMaxLengthFacet ();
1100 max.Value = XmlConvert.ToString (col.MaxLength);
1101 restriction.Facets.Add (max);
1106 private void DoWriteXmlSchema( XmlWriter writer )
1108 GetSchemaSerializable ().Write (writer);
1112 /// Helper function to split columns into attributes elements and simple
1115 private void SplitColumns( DataTable table,
1117 out ArrayList elements,
1118 out DataColumn simple)
1120 //The columns can be attributes, hidden, elements, or simple content
1121 //There can be 0-1 simple content cols or 0-* elements
1122 atts = new System.Collections.ArrayList();
1123 elements = new System.Collections.ArrayList();
1126 //Sort out the columns
1127 foreach( DataColumn col in table.Columns )
1129 switch( col.ColumnMapping )
1131 case MappingType.Attribute:
1134 case MappingType.Element:
1135 elements.Add( col );
1137 case MappingType.SimpleContent:
1138 if( simple != null )
1140 throw new System.InvalidOperationException( "There may only be one simple content element" );
1145 //ignore Hidden elements
1151 private XmlQualifiedName MapType (Type type)
1153 switch (Type.GetTypeCode (type))
1155 case TypeCode.String: return XmlConstants.QnString;
1156 case TypeCode.Int16: return XmlConstants.QnShort;
1157 case TypeCode.Int32: return XmlConstants.QnInt;
1158 case TypeCode.Int64: return XmlConstants.QnLong;
1159 case TypeCode.Boolean: return XmlConstants.QnBoolean;
1160 case TypeCode.Byte: return XmlConstants.QnUnsignedByte;
1161 case TypeCode.Char: return XmlConstants.QnChar;
1162 case TypeCode.DateTime: return XmlConstants.QnDateTime;
1163 case TypeCode.Decimal: return XmlConstants.QnDecimal;
1164 case TypeCode.Double: return XmlConstants.QnDouble;
1165 case TypeCode.SByte: return XmlConstants.QnSbyte;
1166 case TypeCode.Single: return XmlConstants.QnFloat;
1167 case TypeCode.UInt16: return XmlConstants.QnUsignedShort;
1168 case TypeCode.UInt32: return XmlConstants.QnUnsignedInt;
1169 case TypeCode.UInt64: return XmlConstants.QnUnsignedLong;
1172 if (typeof (TimeSpan) == type) return XmlConstants.QnDuration;
1173 else if (typeof (System.Uri) == type) return XmlConstants.QnUri;
1174 else if (typeof (byte[]) == type) return XmlConstants.QnBase64Binary;
1175 else if (typeof (XmlQualifiedName) == type) return XmlConstants.QnXmlQualifiedName;
1176 else return XmlConstants.QnString;
1179 #endregion //Private Xml Serialisation