// 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;
tempTable.AcceptChanges ();
}
+ /// <summary>
+ /// Clears all the tables
+ /// </summary>
public void Clear ()
{
if (_xmlDataDocument != null)
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++) {
+ bool enforceConstraints = this.EnforceConstraints;
+ this.EnforceConstraints = false;
+ for (int t = 0; t < tableCollection.Count; t++) {
tableCollection[t].Clear ();
}
+ this.EnforceConstraints = enforceConstraints;
}
public virtual DataSet Clone ()
{
- DataSet Copy = new DataSet ();
+ // need to return the same type as this...
+ DataSet Copy = (DataSet) Activator.CreateInstance(GetType(), true);
+
CopyProperties (Copy);
foreach (DataTable Table in Tables) {
- Copy.Tables.Add (Table.Clone ());
+ // tables are often added in no-args constructor, don't add them
+ // twice.
+ if (!Copy.Tables.Contains(Table.TableName)) {
+ Copy.Tables.Add (Table.Clone ());
+ }
}
//Copy Relationships between tables after existance of tables
}
DataRow newRow = copyTable.NewRow ();
- copyTable.Rows.Add (newRow);
row.CopyValuesToRow (newRow);
+ copyTable.Rows.Add (newRow);
newRow.XmlRowID = row.XmlRowID;
addedRows.Add (row,row);
}
return ReadXml (new XmlTextReader (reader), mode);
}
- public XmlReadMode ReadXml (XmlReader reader, XmlReadMode mode)
+ // LAMESPEC: XmlReadMode.Fragment is far from presisely
+ // documented. MS.NET infers schema against this mode.
+ public XmlReadMode ReadXml (XmlReader input, XmlReadMode mode)
{
- switch (reader.ReadState) {
+ switch (input.ReadState) {
case ReadState.EndOfFile:
case ReadState.Error:
case ReadState.Closed:
return mode;
}
// Skip XML declaration and prolog
- reader.MoveToContent();
- if (reader.EOF)
+ input.MoveToContent ();
+ if (input.EOF)
return mode;
- XmlReadMode Result = mode;
+ // FIXME: We need more decent code here, but for now
+ // I don't know the precise MS.NET behavior, I just
+ // delegate to specific read process.
+ switch (mode) {
+ case XmlReadMode.IgnoreSchema:
+ return ReadXmlIgnoreSchema (input, mode, true);
+ case XmlReadMode.ReadSchema:
+ return ReadXmlReadSchema (input, mode, true);
+ }
+ // remaining modes are: Auto, InferSchema, Fragment, Diffgram
- // If diffgram, then read the first element as diffgram
- if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
- switch (mode) {
- case XmlReadMode.Auto:
- case XmlReadMode.DiffGram:
- XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
- DiffLoader.Load (reader);
- // (and leave rest of the reader as is)
- return XmlReadMode.DiffGram;
- case XmlReadMode.Fragment:
- reader.Skip ();
- // (and continue to read)
- break;
- default:
- reader.Skip ();
- // (and leave rest of the reader as is)
- return mode;
+ XmlReader reader = input;
+
+ int depth = reader.Depth;
+ XmlReadMode result = mode;
+ bool skippedTopLevelElement = false;
+ string potentialDataSetName = null;
+ XmlDocument doc = null;
+ bool shouldReadData = mode != XmlReadMode.DiffGram;
+ bool shouldNotInfer = Tables.Count > 0;
+
+ switch (mode) {
+ case XmlReadMode.Auto:
+ case XmlReadMode.InferSchema:
+ doc = new XmlDocument ();
+ do {
+ doc.AppendChild (doc.ReadNode (reader));
+ } while (!reader.EOF &&
+ doc.DocumentElement == null);
+ reader = new XmlNodeReader (doc);
+ reader.MoveToContent ();
+ break;
+ case XmlReadMode.DiffGram:
+ if (!(reader.LocalName == "diffgram" &&
+ reader.NamespaceURI == XmlConstants.DiffgrNamespace))
+ goto case XmlReadMode.Auto;
+ break;
+ }
+
+ switch (mode) {
+ case XmlReadMode.Auto:
+ case XmlReadMode.InferSchema:
+ case XmlReadMode.ReadSchema:
+ if (!(reader.LocalName == "diffgram" &&
+ reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
+ !(reader.LocalName == "schema" &&
+ reader.NamespaceURI == XmlSchema.Namespace))
+ potentialDataSetName = reader.LocalName;
+ goto default;
+ case XmlReadMode.Fragment:
+ break;
+ default:
+ if (!(reader.LocalName == "diffgram" &&
+ reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
+ !(reader.LocalName == "schema" &&
+ reader.NamespaceURI == XmlSchema.Namespace)) {
+ if (!reader.IsEmptyElement) {
+ reader.Read ();
+ reader.MoveToContent ();
+ skippedTopLevelElement = true;
+ }
+ else {
+ switch (mode) {
+ case XmlReadMode.Auto:
+ case XmlReadMode.InferSchema:
+ DataSetName = reader.LocalName;
+ break;
+ }
+ reader.Read ();
+ }
}
+ break;
}
+
// If schema, then read the first element as schema
if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
+ shouldNotInfer = true;
switch (mode) {
case XmlReadMode.IgnoreSchema:
case XmlReadMode.InferSchema:
reader.Skip ();
- // (and break up read)
- return mode;
+ break;
case XmlReadMode.Fragment:
ReadXmlSchema (reader);
- // (and continue to read)
break;
+ case XmlReadMode.DiffGram:
case XmlReadMode.Auto:
if (Tables.Count == 0) {
ReadXmlSchema (reader);
- return XmlReadMode.ReadSchema;
+ if (mode == XmlReadMode.Auto)
+ result = XmlReadMode.ReadSchema;
} else {
// otherwise just ignore and return IgnoreSchema
reader.Skip ();
- return XmlReadMode.IgnoreSchema;
+ result = XmlReadMode.IgnoreSchema;
}
- default:
+ break;
+ case XmlReadMode.ReadSchema:
ReadXmlSchema (reader);
- // (and leave rest of the reader as is)
- return mode; // When DiffGram, return DiffGram
+ break;
+ }
+ }
+
+ // If diffgram, then read the first element as diffgram
+ if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
+ switch (mode) {
+ case XmlReadMode.Auto:
+ case XmlReadMode.IgnoreSchema:
+ case XmlReadMode.DiffGram:
+ XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
+ DiffLoader.Load (reader);
+ if (mode == XmlReadMode.Auto)
+ result = XmlReadMode.DiffGram;
+ shouldReadData = false;
+ break;
+ case XmlReadMode.Fragment:
+ reader.Skip ();
+ break;
+ default:
+ reader.Skip ();
+ break;
}
}
+
+ // if schema after diffgram, just skip it.
+ if (!shouldReadData && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
+ shouldNotInfer = true;
+ switch (mode) {
+ default:
+ reader.Skip ();
+ break;
+ case XmlReadMode.ReadSchema:
+ case XmlReadMode.DiffGram:
+ if (Tables.Count == 0)
+ ReadXmlSchema (reader);
+ break;
+ }
+ }
+
+ if (reader.EOF)
+ return result == XmlReadMode.Auto ?
+ potentialDataSetName != null && !shouldNotInfer ?
+ XmlReadMode.InferSchema :
+ XmlReadMode.IgnoreSchema : result;
+
// Otherwise, read as dataset... but only when required.
- bool inferedSchema = false;
- switch (mode) {
- case XmlReadMode.Auto:
- if (Tables.Count > 0)
- goto case XmlReadMode.IgnoreSchema;
- else
- goto case XmlReadMode.InferSchema;
- case XmlReadMode.InferSchema:
-#if true // sync with the switch immediately below
- XmlDocument 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);
-#endif
- inferedSchema = true;
- break;
- case XmlReadMode.IgnoreSchema:
- case XmlReadMode.Fragment:
- break;
- default:
- reader.Skip ();
- return mode;
+ if (shouldReadData && !shouldNotInfer) {
+ switch (mode) {
+ case XmlReadMode.Auto:
+ if (Tables.Count > 0)
+ goto case XmlReadMode.IgnoreSchema;
+ else
+ goto case XmlReadMode.InferSchema;
+ case XmlReadMode.InferSchema:
+ InferXmlSchema (doc, null);
+ if (mode == XmlReadMode.Auto)
+ result = XmlReadMode.InferSchema;
+ break;
+ case XmlReadMode.IgnoreSchema:
+ case XmlReadMode.Fragment:
+ case XmlReadMode.DiffGram:
+ break;
+ default:
+ shouldReadData = false;
+ break;
+ }
}
-#if true // sync with the switch immediately above
- XmlDataReader.ReadXml (this, reader, mode);
- if (inferedSchema)
- return XmlReadMode.InferSchema;
- return mode == XmlReadMode.Auto ? XmlReadMode.IgnoreSchema : mode;
-#else
- XmlDataLoader Loader = new XmlDataLoader (this);
- return Loader.LoadData (reader, mode);
-#endif
+
+ if (shouldReadData) {
+ XmlReader dataReader = reader;
+ if (doc != null) {
+ dataReader = new XmlNodeReader (doc);
+ dataReader.MoveToContent ();
+ }
+ if (reader.NodeType == XmlNodeType.Element)
+ XmlDataReader.ReadXml (this, dataReader,
+ mode);
+ }
+
+ if (skippedTopLevelElement) {
+ switch (result) {
+ case XmlReadMode.Auto:
+ case XmlReadMode.InferSchema:
+// DataSetName = potentialDataSetName;
+// result = XmlReadMode.InferSchema;
+ break;
+ }
+ if (reader.NodeType == XmlNodeType.EndElement)
+ reader.ReadEndElement ();
+ }
+//*
+ while (input.Depth > depth)
+ input.Read ();
+ if (input.NodeType == XmlNodeType.EndElement)
+ input.Read ();
+//*/
+ input.MoveToContent ();
+
+ return result == XmlReadMode.Auto ?
+ XmlReadMode.IgnoreSchema : result;
}
#endregion // Public Methods
#endregion // Public Events
- #region Destructors
-
- ~DataSet ()
- {
- }
-
- #endregion Destructors
-
#region IListSource methods
IList IListSource.GetList ()
{
protected virtual void ReadXmlSerializable (XmlReader reader)
{
- reader.MoveToContent ();
- reader.ReadStartElement ();
- reader.MoveToContent ();
- ReadXmlSchema (reader);
- reader.MoveToContent ();
- ReadXml (reader, XmlReadMode.DiffGram);
- reader.MoveToContent ();
- reader.ReadEndElement ();
+ ReadXml (reader);
}
void IXmlSerializable.ReadXml (XmlReader reader)
WriteXml (writer, XmlWriteMode.DiffGram);
}
- XmlSchema IXmlSerializable.GetSchema ()\r
- {\r
- return BuildSchema ();\r
- }\r
+ XmlSchema IXmlSerializable.GetSchema ()
+ {
+ return GetSchemaSerializable ();
+ }
protected virtual bool ShouldSerializeRelations ()
{
{
}
- protected internal virtual void OnMergeFailed (MergeFailedEventArgs e)
+ internal virtual void OnMergeFailed (MergeFailedEventArgs e)
{
if (MergeFailed != null)
MergeFailed (this, e);
}
#endregion
- #region Private Xml Serialisation
+ #region Private Methods
+
+ private XmlReadMode ReadXmlIgnoreSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
+ {
+ if (input.LocalName == "schema" &&
+ input.NamespaceURI == XmlSchema.Namespace) {
+ input.Skip ();
+ }
+ else if (input.LocalName == "diffgram" &&
+ input.NamespaceURI == XmlConstants.DiffgrNamespace) {
+ XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
+ DiffLoader.Load (input);
+ }
+ else if (checkRecurse ||
+ input.LocalName == DataSetName &&
+ input.NamespaceURI == Namespace) {
+ XmlDataReader.ReadXml (this, input, mode);
+ }
+ else if (checkRecurse && !input.IsEmptyElement) {
+ int depth = input.Depth;
+ input.Read ();
+ input.MoveToContent ();
+ ReadXmlIgnoreSchema (input, mode, false);
+ while (input.Depth > depth)
+ input.Skip ();
+ if (input.NodeType == XmlNodeType.EndElement)
+ input.ReadEndElement ();
+ }
+ input.MoveToContent ();
+ return XmlReadMode.IgnoreSchema;
+ }
+
+ private XmlReadMode ReadXmlReadSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
+ {
+ if (input.LocalName == "schema" &&
+ input.NamespaceURI == XmlSchema.Namespace) {
+ ReadXmlSchema (input);
+ }
+ else if (checkRecurse && !input.IsEmptyElement) {
+ int depth = input.Depth;
+ input.Read ();
+ input.MoveToContent ();
+ ReadXmlReadSchema (input, mode, false);
+ while (input.Depth > depth)
+ input.Skip ();
+ if (input.NodeType == XmlNodeType.EndElement)
+ input.ReadEndElement ();
+ }
+ else
+ input.Skip ();
+ input.MoveToContent ();
+ return XmlReadMode.ReadSchema;
+ }
private string WriteObjectXml (object o)
{
//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);
}
{
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
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 (!oneRel.Nested)
+ break;
+ if (row.GetParentRow (oneRel) != null)
+ continue;
+ break;
+ case 2:
+ bool skip = false;
+ for (int i = 0; i < table.ParentRelations.Count; i++) {
+ DataRelation prel = table.ParentRelations [i];
+ if (!prel.Nested)
+ continue;
+ if (row.GetParentRow (prel) != null) {
+ skip = true;
+ continue;
+ }
+ }
+ if (skip)
+ continue;
+ break;
+ }
+ }
+
if (!row.HasVersion(version) ||
(mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged
&& version == DataRowVersion.Original))
// 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;
}
foreach (DataRelation relation in table.ChildRelations) {
if (relation.Nested) {
- WriteTable (writer, row.GetChildRows (relation), mode, version);
+ WriteTable (writer, row.GetChildRows (relation), mode, version, false);
}
}
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 ());
+ if (!row.IsNull (col))
+ 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)
//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";
}
writer.WriteEndElement (); // DataSet name or diffgr:diffgram
}
+
private void CheckNamespace (string prefix, string ns, XmlNamespaceManager nsmgr, XmlSchema schema)
{
if (ns == String.Empty)
return;
if (ns != nsmgr.DefaultNamespace) {
- if (nsmgr.LookupNamespace (prefix) != ns) {
+ 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)) {
}
// set the schema id
- string xmlNSURI = "http://www.w3.org/2000/xmlns/";
schema.Id = DataSetName;
XmlDocument doc = new XmlDocument ();
XmlAttribute attr = null;
ArrayList atts = new ArrayList ();
+ attr = doc.CreateAttribute ("", "xmlns", XmlConstants.XmlnsNS);
+ atts.Add (attr);
+
nsmgr.AddNamespace ("xs", XmlSchema.Namespace);
nsmgr.AddNamespace (XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
if (Namespace != "") {
nsmgr.AddNamespace (XmlConstants.TnsPrefix, Namespace);
nsmgr.AddNamespace (String.Empty, Namespace);
}
+ if (CheckExtendedPropertyExists (tables, relations))
+ nsmgr.AddNamespace (XmlConstants.MspropPrefix, XmlConstants.MspropNamespace);
if (atts.Count > 0)
schema.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
elem.Name = XmlConvert.EncodeName (DataSetName);
// Add namespaces used in DataSet components (tables, columns, ...)
- foreach (DataTable dt in Tables) {
+ 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);
elem.UnhandledAttributes = atts.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+ AddExtendedPropertyAttributes (elem, ExtendedProperties, doc);
+
XmlSchemaComplexType complex = new XmlSchemaComplexType ();
elem.SchemaType = complex;
schema.Items.Add (elem);
- AddConstraintsToSchema (elem, constraintPrefix, tables, relations);
+ AddConstraintsToSchema (elem, constraintPrefix, tables, relations, doc);
foreach (string prefix in nsmgr) {
- string ns = nsmgr.LookupNamespace (prefix);
+ 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;
}
-
+
+ private bool CheckExtendedPropertyExists (
+ DataTableCollection tables,
+ DataRelationCollection relations)
+ {
+ if (ExtendedProperties.Count > 0)
+ return true;
+ foreach (DataTable dt in tables) {
+ if (dt.ExtendedProperties.Count > 0)
+ return true;
+ foreach (DataColumn col in dt.Columns)
+ if (col.ExtendedProperties.Count > 0)
+ return true;
+ foreach (Constraint c in dt.Constraints)
+ if (c.ExtendedProperties.Count > 0)
+ return true;
+ }
+ if (relations == null)
+ return false;
+ foreach (DataRelation rel in relations)
+ if (rel.ExtendedProperties.Count > 0)
+ return true;
+ return false;
+ }
+
// Add all constraints in all tables to the schema.
- private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations)
+ private void AddConstraintsToSchema (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, DataRelationCollection relations, XmlDocument doc)
{
// first add all unique constraints.
- Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables);
+ Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables, doc);
// Add all foriegn key constraints.
- AddForeignKeys (uniqueNames, elem, constraintPrefix, relations);
+ AddForeignKeys (uniqueNames, elem, constraintPrefix, relations, doc);
}
// Add unique constaraints to the schema.
// return hashtable with the names of all XmlSchemaUnique elements we created.
- private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables)
+ private Hashtable AddUniqueConstraints (XmlSchemaElement elem, string constraintPrefix, DataTableCollection tables, XmlDocument doc)
{
- XmlDocument doc = new XmlDocument();
Hashtable uniqueNames = new Hashtable();
foreach (DataTable table in tables) {
- foreach (Constraint constaint in table.Constraints) {
+ foreach (Constraint constraint in table.Constraints) {
- if (constaint is UniqueConstraint) {
+ if (constraint is UniqueConstraint) {
ArrayList attrs = new ArrayList ();
XmlAttribute attrib;
- UniqueConstraint uqConst = (UniqueConstraint)constaint;
+ UniqueConstraint uqConst = (UniqueConstraint) constraint;
XmlSchemaUnique uniq = new XmlSchemaUnique ();
// if column of the constraint is hidden do not write the constraint.
XmlSchemaXPath field;
foreach (DataColumn column in uqConst.Columns) {
field = new XmlSchemaXPath();
- field.XPath = constraintPrefix+column.ColumnName;
+ string typePrefix = column.ColumnMapping == MappingType.Attribute ? "@" : "";
+ field.XPath = typePrefix + constraintPrefix+column.ColumnName;
uniq.Fields.Add(field);
}
+ AddExtendedPropertyAttributes (uniq, constraint.ExtendedProperties, doc);
+
elem.Constraints.Add (uniq);
uniqueNames.Add (uniq.Name, null);
}
}
// Add the foriegn keys to the schema.
- private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations)
+ private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations, XmlDocument doc)
{
if (relations == null) return;
- XmlDocument doc = new XmlDocument();
foreach (DataRelation rel in relations) {
if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null)
XmlSchemaXPath field;
foreach (DataColumn column in rel.ChildColumns) {
field = new XmlSchemaXPath();
- field.XPath = constraintPrefix+column.ColumnName;
+ string typePrefix = column.ColumnMapping == MappingType.Attribute ? "@" : "";
+ field.XPath = typePrefix + constraintPrefix + column.ColumnName;
keyRef.Fields.Add(field);
}
+
keyRef.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
+ AddExtendedPropertyAttributes (keyRef, rel.ExtendedProperties, doc);
+
elem.Constraints.Add (keyRef);
}
}
ArrayList elements;
ArrayList atts;
DataColumn simple;
-
+
+ ArrayList xattrs = new ArrayList();
+ XmlAttribute xattr;
+
SplitColumns (table, out atts, out elements, out simple);
XmlSchemaElement elem = new XmlSchemaElement ();
XmlSchemaObjectCollection schemaAttributes = null;
- //TODO - what about the simple content?
if (simple != null) {
// add simpleContent
XmlSchemaSimpleContent simpleContent = new XmlSchemaSimpleContent();
// 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;
// Add element for the column.
XmlSchemaElement colElem = new XmlSchemaElement ();
- ArrayList xattrs = new ArrayList();
- XmlAttribute xattr;
colElem.Name = col.ColumnName;
if (col.ColumnName != col.Caption && col.Caption != String.Empty) {
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.ReadOnly) {
+ xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ReadOnly, XmlConstants.MsdataNamespace);
+ xattr.Value = "true";
+ xattrs.Add (xattr);
+ }
+
if (col.MaxLength < 0)
colElem.SchemaTypeName = MapType (col.DataType);
}
colElem.UnhandledAttributes = (XmlAttribute[])xattrs.ToArray(typeof (XmlAttribute));
+ xattrs.Clear ();
+ AddExtendedPropertyAttributes (colElem, col.ExtendedProperties, doc);
seq.Items.Add (colElem);
}
- if (seq.Items.Count > 0)
- complex.Particle = seq;
foreach (DataRelation rel in table.ChildRelations) {
if (rel.Nested) {
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;
}
}
}
+
+ if (seq.Items.Count > 0)
+ complex.Particle = seq;
}
//Then a list of attributes
// FIXME: Handle prefix mapping correctly.
schemaToAdd.Namespaces.Add (prefix, col.Namespace);
}
- att.SchemaTypeName = MapType (col.DataType);
+ if (!col.AllowDBNull)
+ att.Use = XmlSchemaUse.Required;
+ if (col.DefaultValue.ToString () != String.Empty)
+ att.DefaultValue = WriteObjectXml (col.DefaultValue);
+
+ if (col.ReadOnly) {
+ xattr = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ReadOnly, XmlConstants.MsdataNamespace);
+ xattr.Value = "true";
+ xattrs.Add (xattr);
+ }
+
+ att.UnhandledAttributes = xattrs.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+ xattrs.Clear ();
+
+ if (col.MaxLength > -1)
+ att.SchemaType = GetTableSimpleType (doc, col);
+ else
+ att.SchemaTypeName = MapType (col.DataType);
+ // FIXME: what happens if extended properties are set on attribute columns??
schemaAttributes.Add (att);
}
+ AddExtendedPropertyAttributes (elem, table.ExtendedProperties, doc);
+
return elem;
}
+ private void AddExtendedPropertyAttributes (XmlSchemaAnnotated xsobj, PropertyCollection props, XmlDocument doc)
+ {
+ ArrayList attList = new ArrayList ();
+ XmlAttribute xmlAttr;
+
+ if (xsobj.UnhandledAttributes != null)
+ attList.AddRange (xsobj.UnhandledAttributes);
+
+ // add extended properties to xs:element
+ foreach (DictionaryEntry de in props) {
+ xmlAttr = doc.CreateAttribute (XmlConstants.MspropPrefix, XmlConvert.EncodeName (de.Key.ToString ()), XmlConstants.MspropNamespace);
+ xmlAttr.Value = de.Value != null ? WriteObjectXml (de.Value) : String.Empty;
+ attList.Add (xmlAttr);
+ }
+ if (attList.Count > 0)
+ xsobj.UnhandledAttributes = attList.ToArray (typeof (XmlAttribute)) as XmlAttribute [];
+ }
+
private string SafeNS (string ns)
{
return ns != null ? ns : String.Empty;