X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Data%2FSystem.Data%2FDataSet.cs;h=49ae0f024f96056d5ef7b4fdcc4429ff015bba5e;hb=cbe75fb35eabdffbfdca49f08f87d7d6b3110f21;hp=2bf8268c043699acf913f796776330902129e4d9;hpb=fffc6aee71033f2859be042e12083587b1a7365a;p=mono.git diff --git a/mcs/class/System.Data/System.Data/DataSet.cs b/mcs/class/System.Data/System.Data/DataSet.cs index 2bf8268c043..49ae0f024f9 100644 --- a/mcs/class/System.Data/System.Data/DataSet.cs +++ b/mcs/class/System.Data/System.Data/DataSet.cs @@ -14,6 +14,29 @@ // Copyright (C) Tim Coleman, 2002, 2003 // +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + using System; using System.Collections; using System.ComponentModel; @@ -30,6 +53,8 @@ namespace System.Data { [ToolboxItem (false)] [DefaultProperty ("DataSetName")] + [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataSetDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")] + [Serializable] public class DataSet : MarshalByValueComponent, IListSource, ISupportInitialize, ISerializable, IXmlSerializable @@ -63,10 +88,9 @@ namespace System.Data { this.Locale = CultureInfo.CurrentCulture; } - [MonoTODO] protected DataSet (SerializationInfo info, StreamingContext context) : this () { - throw new NotImplementedException (); + GetSerializationData (info, context); } #endregion // Constructors @@ -81,11 +105,6 @@ namespace System.Data { return caseSensitive; } set { - foreach (DataTable T in Tables) { - if (T.VirginCaseSensitive) - T.CaseSensitive = value; - } - caseSensitive = value; if (!caseSensitive) { foreach (DataTable table in Tables) { @@ -235,12 +254,14 @@ namespace System.Data { [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")] [DefaultValue ("")] public string Namespace { - [MonoTODO] get { return _namespace; } - [MonoTODO] set { //TODO - trigger an event if this happens? - _namespace = value; + if (value == null) + value = String.Empty; + if (value != this._namespace) + RaisePropertyChanging ("Namespace"); + _namespace = value; } } @@ -248,11 +269,16 @@ namespace System.Data { [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")] [DefaultValue ("")] public string Prefix { - [MonoTODO] get { return prefix; } - [MonoTODO] set { - //TODO - trigger an event if this happens? + if (value == null) + value = String.Empty; + // Prefix cannot contain any special characters other than '_' and ':' + for (int i = 0; i < value.Length; i++) { + if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':')) + throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters."); + } + if (value == null) value = string.Empty; @@ -307,7 +333,7 @@ namespace System.Data { public void Clear () { if (_xmlDataDocument != null) - throw new NotSupportedException ("Clear function on dataset and datatable is not supported on XmlDataDocument."); + throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet."); for (int t = 0; t < tableCollection.Count; t++) { tableCollection[t].Clear (); } @@ -346,7 +372,6 @@ namespace System.Data { return Copy; } - [MonoTODO] private void CopyProperties (DataSet Copy) { Copy.CaseSensitive = CaseSensitive; @@ -355,12 +380,17 @@ namespace System.Data { //Copy.DefaultViewManager //Copy.DesignMode Copy.EnforceConstraints = EnforceConstraints; - //Copy.ExtendedProperties - //Copy.HasErrors - //Copy.Locale = Locale; + if(ExtendedProperties.Count > 0) { + // Cannot copy extended properties directly as the property does not have a set accessor + Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count); + ExtendedProperties.Keys.CopyTo (tgtArray, 0); + for (int i=0; i < ExtendedProperties.Count; i++) + Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]); + } + Copy.Locale = Locale; Copy.Namespace = Namespace; Copy.Prefix = Prefix; - //Copy.Site = Site; + //Copy.Site = Site; // FIXME : Not sure of this. } @@ -460,7 +490,7 @@ namespace System.Data { addedRows.Add (row,row); } -#if NET_1_2 +#if NET_2_0 [MonoTODO] public DataTableReader GetDataReader (DataTable[] dataTables) { @@ -477,8 +507,6 @@ namespace System.Data { public string GetXml () { StringWriter Writer = new StringWriter (); - - // Sending false for not printing the Processing instruction WriteXml (Writer, XmlWriteMode.IgnoreSchema); return Writer.ToString (); } @@ -520,10 +548,18 @@ namespace System.Data { return false; } - [MonoTODO] public void InferXmlSchema (XmlReader reader, string[] nsArray) { - throw new NotImplementedException (); + if (reader == null) + return; + XmlDocument doc = new XmlDocument (); + doc.Load (reader); + InferXmlSchema (doc, nsArray); + } + + private void InferXmlSchema (XmlDocument doc, string [] nsArray) + { + XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray); } public void InferXmlSchema (Stream stream, string[] nsArray) @@ -546,7 +582,7 @@ namespace System.Data { } } -#if NET_1_2 +#if NET_2_0 [MonoTODO] public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables) { @@ -663,27 +699,36 @@ namespace System.Data { SetRowsID(); WriteDiffGramElement(writer); } - - string ns = Namespace == null ? String.Empty : Namespace; - - WriteStartElement (writer, mode, ns, Prefix, XmlConvert.EncodeName (DataSetName)); - if (mode == XmlWriteMode.WriteSchema) { - DoWriteXmlSchema (writer); + // It should not write when there is no content to be written + bool shouldOutputContent = (mode != XmlWriteMode.DiffGram); + for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++) + shouldOutputContent = tableCollection [n].Rows.Count > 0; + + if (shouldOutputContent) { + WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName)); + + if (mode == XmlWriteMode.WriteSchema) + DoWriteXmlSchema (writer); + + WriteTables (writer, mode, Tables, DataRowVersion.Default); + writer.WriteEndElement (); } - WriteTables (writer, mode, Tables, DataRowVersion.Default); if (mode == XmlWriteMode.DiffGram) { - writer.WriteEndElement (); //DataSet name if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) { - DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted); + DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted); WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before"); WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original); writer.WriteEndElement (); } } - writer.WriteEndElement (); // DataSet name or diffgr:diffgram + + if (mode == XmlWriteMode.DiffGram) + writer.WriteEndElement (); // diffgr:diffgram + + writer.Flush (); } public void WriteXmlSchema (Stream stream) @@ -696,12 +741,11 @@ namespace System.Data { public void WriteXmlSchema (string fileName) { XmlTextWriter writer = new XmlTextWriter (fileName, null); - writer.Formatting = Formatting.Indented; - writer.WriteStartDocument (true); try { + writer.Formatting = Formatting.Indented; + writer.WriteStartDocument (true); WriteXmlSchema (writer); - } - finally { + } finally { writer.WriteEndDocument (); writer.Close (); } @@ -710,8 +754,14 @@ namespace System.Data { public void WriteXmlSchema (TextWriter writer) { XmlTextWriter xwriter = new XmlTextWriter (writer); - xwriter.Formatting = Formatting.Indented; - WriteXmlSchema (xwriter); + try { + xwriter.Formatting = Formatting.Indented; +// xwriter.WriteStartDocument (); + WriteXmlSchema (xwriter); + } finally { +// xwriter.WriteEndDocument (); + xwriter.Close (); + } } public void WriteXmlSchema (XmlWriter writer) @@ -746,8 +796,12 @@ namespace System.Data { public void ReadXmlSchema (XmlReader reader) { +#if true + new XmlSchemaDataImporter (this, reader).Process (); +#else XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this); SchemaMapper.Read (reader); +#endif } public XmlReadMode ReadXml (Stream stream) @@ -797,7 +851,6 @@ namespace System.Data { return ReadXml (new XmlTextReader (reader), mode); } - [MonoTODO] public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode) { switch (reader.ReadState) { @@ -832,7 +885,6 @@ namespace System.Data { return mode; } } - XmlSchemaMapper SchemaMapper = null; // If schema, then read the first element as schema if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) { switch (mode) { @@ -842,29 +894,74 @@ namespace System.Data { // (and break up read) return mode; case XmlReadMode.Fragment: - SchemaMapper = new XmlSchemaMapper (this); - SchemaMapper.Read (reader); + ReadXmlSchema (reader); // (and continue to read) break; + case XmlReadMode.Auto: + if (Tables.Count == 0) { + ReadXmlSchema (reader); + return XmlReadMode.ReadSchema; + } else { + // otherwise just ignore and return IgnoreSchema + reader.Skip (); + return XmlReadMode.IgnoreSchema; + } default: - SchemaMapper = new XmlSchemaMapper (this); - SchemaMapper.Read (reader); + ReadXmlSchema (reader); // (and leave rest of the reader as is) - return XmlReadMode.ReadSchema; + return mode; // When DiffGram, return DiffGram } } // Otherwise, read as dataset... but only when required. + XmlReadMode explicitReturnMode = XmlReadMode.Auto; + XmlDocument doc; switch (mode) { case XmlReadMode.Auto: + if (Tables.Count > 0) + goto case XmlReadMode.IgnoreSchema; + else + goto case XmlReadMode.InferSchema; case XmlReadMode.InferSchema: + doc = new XmlDocument (); + do { + doc.AppendChild (doc.ReadNode (reader)); + reader.MoveToContent (); + if (doc.DocumentElement != null) + break; + } while (!reader.EOF); + InferXmlSchema (doc, null); + reader = new XmlNodeReader (doc); + explicitReturnMode = XmlReadMode.InferSchema; + break; + case XmlReadMode.ReadSchema: + doc = new XmlDocument (); + do { + doc.AppendChild (doc.ReadNode (reader)); + reader.MoveToContent (); + if (doc.DocumentElement != null) + break; + } while (!reader.EOF); + if (doc.DocumentElement != null) { + XmlElement schema = doc.DocumentElement ["schema", XmlSchema.Namespace] as XmlElement; + if (schema != null) { + ReadXmlSchema (new XmlNodeReader (schema)); + explicitReturnMode = XmlReadMode.ReadSchema; + } + } + reader = new XmlNodeReader (doc); + break; + case XmlReadMode.IgnoreSchema: case XmlReadMode.Fragment: break; default: reader.Skip (); return mode; } - XmlDataLoader Loader = new XmlDataLoader (this); - return Loader.LoadData (reader, mode); + + XmlDataReader.ReadXml (this, reader, mode); + if (explicitReturnMode != XmlReadMode.Auto) + return explicitReturnMode; + return mode == XmlReadMode.Auto ? XmlReadMode.IgnoreSchema : mode; } #endregion // Public Methods @@ -876,14 +973,6 @@ namespace System.Data { #endregion // Public Events - #region Destructors - - ~DataSet () - { - } - - #endregion Destructors - #region IListSource methods IList IListSource.GetList () { @@ -910,15 +999,32 @@ namespace System.Data { #region ISerializable void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc) { - throw new NotImplementedException (); + StringWriter sw = new StringWriter (); + XmlTextWriter writer = new XmlTextWriter (sw); + DoWriteXmlSchema (writer); + writer.Flush (); + si.AddValue ("XmlSchema", sw.ToString ()); + + sw = new StringWriter (); + writer = new XmlTextWriter (sw); + WriteXml (writer, XmlWriteMode.DiffGram); + writer.Flush (); + si.AddValue ("XmlDiffGram", sw.ToString ()); } #endregion #region Protected Methods protected void GetSerializationData (SerializationInfo info, StreamingContext context) { - string s = info.GetValue ("XmlDiffGram", typeof (String)) as String; - if (s != null) ReadXmlSerializable (new XmlTextReader (new StringReader (s))); + string s = info.GetValue ("XmlSchema", typeof (String)) as String; + XmlTextReader reader = new XmlTextReader (new StringReader (s)); + ReadXmlSchema (reader); + reader.Close (); + + s = info.GetValue ("XmlDiffGram", typeof (String)) as String; + reader = new XmlTextReader (new StringReader (s)); + ReadXml (reader, XmlReadMode.DiffGram); + reader.Close (); } @@ -929,17 +1035,19 @@ namespace System.Data { protected virtual void ReadXmlSerializable (XmlReader reader) { - ReadXml (reader, XmlReadMode.DiffGram); // FIXME + reader.MoveToContent (); + reader.ReadStartElement (); + reader.MoveToContent (); + ReadXmlSchema (reader); + reader.MoveToContent (); + ReadXml (reader, XmlReadMode.DiffGram); + reader.MoveToContent (); + reader.ReadEndElement (); } void IXmlSerializable.ReadXml (XmlReader reader) { - ReadXmlSerializable(reader); - - // the XmlSerializationReader does this lines!!! - //reader.MoveToContent (); - //reader.ReadEndElement (); // } void IXmlSerializable.WriteXml (XmlWriter writer) @@ -948,6 +1056,11 @@ namespace System.Data { WriteXml (writer, XmlWriteMode.DiffGram); } + XmlSchema IXmlSerializable.GetSchema () + { + return BuildSchema (); + } + protected virtual bool ShouldSerializeRelations () { return true; @@ -973,7 +1086,7 @@ namespace System.Data { { } - protected internal virtual void OnMergeFailed (MergeFailedEventArgs e) + internal virtual void OnMergeFailed (MergeFailedEventArgs e) { if (MergeFailed != null) MergeFailed (this, e); @@ -1031,13 +1144,14 @@ namespace System.Data { //part of another table structure via a nested parent relationship foreach (DataTable table in tableCollection) { bool isTopLevel = true; + /* foreach (DataRelation rel in table.ParentRelations) { if (rel.Nested) { isTopLevel = false; break; } } - + */ if (isTopLevel) { WriteTable ( writer, table, mode, version); } @@ -1048,10 +1162,10 @@ namespace System.Data { { DataRow[] rows = new DataRow [table.Rows.Count]; table.Rows.CopyTo (rows, 0); - WriteTable (writer, rows, mode, version); + WriteTable (writer, rows, mode, version, true); } - private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version) + private void WriteTable (XmlWriter writer, DataRow[] rows, XmlWriteMode mode, DataRowVersion version, bool skipIfNested) { //The columns can be attributes, hidden, elements, or simple content //There can be 0-1 simple content cols or 0-* elements @@ -1064,8 +1178,32 @@ namespace System.Data { SplitColumns (table, out atts, out elements, out simple); //sort out the namespacing string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace; + int relationCount = table.ParentRelations.Count; + DataRelation oneRel = relationCount == 1 ? table.ParentRelations [0] : null; foreach (DataRow row in rows) { + if (skipIfNested) { + // Skip rows that is a child of any tables. + switch (relationCount) { + case 0: + break; + case 1: + if (row.GetParentRow (oneRel) != null) + continue; + break; + case 2: + bool skip = false; + for (int i = 0; i < table.ParentRelations.Count; i++) + if (row.GetParentRow (table.ParentRelations [i]) != null) { + skip = true; + continue; + } + if (skip) + continue; + break; + } + } + if (!row.HasVersion(version) || (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged && version == DataRowVersion.Original)) @@ -1083,7 +1221,7 @@ namespace System.Data { // If all of the columns were null, we have to write empty element if (AllNulls) { - writer.WriteElementString (table.TableName, ""); + writer.WriteElementString (XmlConvert.EncodeLocalName (table.TableName), ""); continue; } @@ -1098,13 +1236,13 @@ namespace System.Data { } else { foreach (DataColumn col in elements) { - WriteColumnAsElement (writer, mode, nspc, col, row, version); + WriteColumnAsElement (writer, mode, col, row, version); } } foreach (DataRelation relation in table.ChildRelations) { if (relation.Nested) { - WriteTable (writer, row.GetChildRows (relation), mode, version); + WriteTable (writer, row.GetChildRows (relation), mode, version, false); } } @@ -1113,27 +1251,26 @@ namespace System.Data { } - private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, string nspc, DataColumn col, DataRow row, DataRowVersion version) + private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version) { - string colnspc = nspc; + string colnspc = null; object rowObject = row [col, version]; if (rowObject == null || rowObject == DBNull.Value) return; - if (col.Namespace != null) { + if (col.Namespace != String.Empty) colnspc = col.Namespace; - } //TODO check if I can get away with write element string - WriteStartElement (writer, mode, colnspc, col.Prefix, col.ColumnName); + WriteStartElement (writer, mode, colnspc, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName)); writer.WriteString (WriteObjectXml (rowObject)); writer.WriteEndElement (); } private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version) { - WriteAttributeString (writer, mode, col.Namespace, col.Prefix, col.ColumnName, row[col, version].ToString ()); + WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName), WriteObjectXml (row[col, version])); } private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version) @@ -1141,11 +1278,11 @@ namespace System.Data { //sort out the namespacing string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace; - WriteStartElement (writer, mode, nspc, table.Prefix, table.TableName); + WriteStartElement (writer, mode, nspc, table.Prefix, XmlConvert.EncodeLocalName (table.TableName)); if (mode == XmlWriteMode.DiffGram) { WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1)); - WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", row.XmlRowID.ToString()); + WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID)); string modeName = null; if (row.RowState == DataRowState.Modified) modeName = "modified"; @@ -1202,10 +1339,24 @@ namespace System.Data { } writer.WriteEndElement (); // DataSet name or diffgr:diffgram } + - XmlSchema IXmlSerializable.GetSchema () + private void CheckNamespace (string prefix, string ns, XmlNamespaceManager nsmgr, XmlSchema schema) { - return BuildSchema (); + if (ns == String.Empty) + return; + if (ns != nsmgr.DefaultNamespace) { + if (nsmgr.LookupNamespace (nsmgr.NameTable.Get (prefix)) != ns) { + for (int i = 1; i < int.MaxValue; i++) { + string p = nsmgr.NameTable.Add ("app" + i); + if (!nsmgr.HasNamespace (p)) { + nsmgr.AddNamespace (p, ns); + HandleExternalNamespace (p, ns, schema); + break; + } + } + } + } } XmlSchema BuildSchema () @@ -1217,39 +1368,53 @@ namespace System.Data { { string constraintPrefix = ""; XmlSchema schema = new XmlSchema (); - - schema.Namespaces.Add("xs", XmlSchema.Namespace); - schema.Namespaces.Add(XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace); + XmlNamespaceManager nsmgr = new XmlNamespaceManager (new NameTable ()); - if (Namespace != "" && Namespace != null) { + if (Namespace != "") { schema.AttributeFormDefault = XmlSchemaForm.Qualified; schema.ElementFormDefault = XmlSchemaForm.Qualified; schema.TargetNamespace = Namespace; - schema.Namespaces.Add(XmlConstants.TnsPrefix, Namespace); constraintPrefix = XmlConstants.TnsPrefix + ":"; } - + // set the schema id + string xmlNSURI = "http://www.w3.org/2000/xmlns/"; schema.Id = DataSetName; XmlDocument doc = new XmlDocument (); - XmlAttribute xmlnsAttr = doc.CreateAttribute("xmlns"); - xmlnsAttr.Value = Namespace; + XmlAttribute attr = null; + ArrayList atts = new ArrayList (); + + nsmgr.AddNamespace ("xs", XmlSchema.Namespace); + nsmgr.AddNamespace (XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace); + if (Namespace != "") { + nsmgr.AddNamespace (XmlConstants.TnsPrefix, Namespace); + nsmgr.AddNamespace (String.Empty, Namespace); + } - schema.UnhandledAttributes = new XmlAttribute[] {xmlnsAttr}; + if (atts.Count > 0) + schema.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute []; XmlSchemaElement elem = new XmlSchemaElement (); elem.Name = XmlConvert.EncodeName (DataSetName); - XmlAttribute[] atts = new XmlAttribute [2]; - atts[0] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace); - atts[0].Value = "true"; + // Add namespaces used in DataSet components (tables, columns, ...) + foreach (DataTable dt in Tables) { + foreach (DataColumn col in dt.Columns) + CheckNamespace (col.Prefix, col.Namespace, nsmgr, schema); + CheckNamespace (dt.Prefix, dt.Namespace, nsmgr, schema); + } - atts[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace); - atts[1].Value = locale.Name; + // Attributes for DataSet element + atts.Clear (); + attr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsDataSet, XmlConstants.MsdataNamespace); + attr.Value = "true"; + atts.Add (attr); - elem.UnhandledAttributes = atts; + attr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Locale, XmlConstants.MsdataNamespace); + attr.Value = locale.Name; + atts.Add (attr); - schema.Items.Add (elem); + elem.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute []; XmlSchemaComplexType complex = new XmlSchemaComplexType (); elem.SchemaType = complex; @@ -1268,12 +1433,25 @@ namespace System.Data { } } - if (isTopLevel){ - choice.Items.Add (GetTableSchema (doc, table)); + if (isTopLevel) { + if (table.Namespace != SafeNS (schema.TargetNamespace)) { + XmlSchemaElement extElem = new XmlSchemaElement (); + extElem.RefName = new XmlQualifiedName (table.TableName, table.Namespace); + choice.Items.Add (extElem); + } + else + choice.Items.Add (GetTableSchema (doc, table, schema, nsmgr)); } } + + schema.Items.Add (elem); AddConstraintsToSchema (elem, constraintPrefix, tables, relations); + foreach (string prefix in nsmgr) { + string ns = nsmgr.LookupNamespace (nsmgr.NameTable.Get (prefix)); + if (prefix != "xmlns" && prefix != "xml" && ns != null && ns != String.Empty) + schema.Namespaces.Add (prefix, ns); + } return schema; } @@ -1360,6 +1538,22 @@ namespace System.Data { if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null) continue; + + bool isHidden = false; + foreach (DataColumn col in rel.ParentColumns) { + if (col.ColumnMapping == MappingType.Hidden) { + isHidden = true; + break; + } + } + foreach (DataColumn col in rel.ChildColumns) { + if (col.ColumnMapping == MappingType.Hidden) { + isHidden = true; + break; + } + } + if (isHidden) + continue; ArrayList attrs = new ArrayList (); XmlAttribute attrib; @@ -1396,7 +1590,7 @@ namespace System.Data { } } - private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table) + private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table, XmlSchema schemaToAdd, XmlNamespaceManager nsmgr) { ArrayList elements; ArrayList atts; @@ -1410,7 +1604,8 @@ namespace System.Data { XmlSchemaComplexType complex = new XmlSchemaComplexType (); elem.SchemaType = complex; - //TODO - what about the simple content? + XmlSchemaObjectCollection schemaAttributes = null; + if (simple != null) { // add simpleContent XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent(); @@ -1423,7 +1618,7 @@ namespace System.Data { // add ordinal attribute xlmAttrs[1] = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.Ordinal, XmlConstants.MsdataNamespace); - xlmAttrs[1].Value = simple.Ordinal.ToString(); + xlmAttrs[1].Value = XmlConvert.ToString (simple.Ordinal); simpleContent.UnhandledAttributes = xlmAttrs; @@ -1431,13 +1626,12 @@ namespace System.Data { XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension(); simpleContent.Content = extension; extension.BaseTypeName = MapType (simple.DataType); - - } - else { + schemaAttributes = extension.Attributes; + } else { + schemaAttributes = complex.Attributes; //A sequence of element types or a simple content node // XmlSchemaSequence seq = new XmlSchemaSequence (); - complex.Particle = seq; foreach (DataColumn col in elements) { @@ -1461,12 +1655,12 @@ namespace System.Data { if (col.AutoIncrementSeed != 0) { xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.AutoIncrementSeed, XmlConstants.MsdataNamespace); - xattr.Value = col.AutoIncrementSeed.ToString(); + xattr.Value = XmlConvert.ToString (col.AutoIncrementSeed); xattrs.Add (xattr); } if (col.DefaultValue.ToString () != String.Empty) - colElem.DefaultValue = col.DefaultValue.ToString (); + colElem.DefaultValue = WriteObjectXml (col.DefaultValue); if (col.MaxLength < 0) colElem.SchemaTypeName = MapType (col.DataType); @@ -1474,7 +1668,7 @@ namespace System.Data { if (colElem.SchemaTypeName == XmlConstants.QnString && col.DataType != typeof (string) && col.DataType != typeof (char)) { xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.DataType, XmlConstants.MsdataNamespace); - xattr.Value = col.DataType.ToString(); + xattr.Value = col.DataType.AssemblyQualifiedName; xattrs.Add (xattr); } @@ -1498,9 +1692,25 @@ namespace System.Data { foreach (DataRelation rel in table.ChildRelations) { if (rel.Nested) { - seq.Items.Add(GetTableSchema (doc, rel.ChildTable)); + if (rel.ChildTable.Namespace != SafeNS (schemaToAdd.TargetNamespace)) { + XmlSchemaElement el = new XmlSchemaElement (); + el.RefName = new XmlQualifiedName (rel.ChildTable.TableName, rel.ChildTable.Namespace); + } else { + XmlSchemaElement el = GetTableSchema (doc, rel.ChildTable, schemaToAdd, nsmgr); + el.MinOccurs = 0; + el.MaxOccursString = "unbounded"; + XmlSchemaComplexType ct = (XmlSchemaComplexType) el.SchemaType; + ct.Name = el.Name; + el.SchemaType = null; + el.SchemaTypeName = new XmlQualifiedName (ct.Name, schemaToAdd.TargetNamespace); + schemaToAdd.Items.Add (ct); + seq.Items.Add (el); + } } } + + if (seq.Items.Count > 0) + complex.Particle = seq; } //Then a list of attributes @@ -1508,14 +1718,38 @@ namespace System.Data { // XmlSchemaAttribute att = new XmlSchemaAttribute (); att.Name = col.ColumnName; - att.Form = XmlSchemaForm.Unqualified; + if (col.Namespace != String.Empty) { + att.Form = XmlSchemaForm.Qualified; + string prefix = col.Prefix == String.Empty ? "app" + schemaToAdd.Namespaces.Count : col.Prefix; + att.Name = prefix + ":" + col.ColumnName; + // FIXME: Handle prefix mapping correctly. + schemaToAdd.Namespaces.Add (prefix, col.Namespace); + } att.SchemaTypeName = MapType (col.DataType); - complex.Attributes.Add (att); + schemaAttributes.Add (att); } return elem; } + private string SafeNS (string ns) + { + return ns != null ? ns : String.Empty; + } + + private void HandleExternalNamespace (string prefix, string ns, XmlSchema schema) + { + foreach (XmlSchemaExternal ext in schema.Includes) { + XmlSchemaImport imp = ext as XmlSchemaImport; + if (imp != null && imp.Namespace == ns) + return; // nothing to do + } + XmlSchemaImport i = new XmlSchemaImport (); + i.Namespace = ns; + i.SchemaLocation = "_" + prefix + ".xsd"; + schema.Includes.Add (i); + } + private XmlSchemaSimpleType GetTableSimpleType (XmlDocument doc, DataColumn col) { // SimpleType