+ 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, XmlDocument doc)
+ {
+ // first add all unique constraints.
+ Hashtable uniqueNames = AddUniqueConstraints (elem, constraintPrefix, tables, doc);
+ // Add all foriegn key constraints.
+ 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, XmlDocument doc)
+ {
+ Hashtable uniqueNames = new Hashtable();
+ foreach (DataTable table in tables) {
+
+ foreach (Constraint constraint in table.Constraints) {
+
+ if (constraint is UniqueConstraint) {
+ ArrayList attrs = new ArrayList ();
+ XmlAttribute attrib;
+ UniqueConstraint uqConst = (UniqueConstraint) constraint;
+ XmlSchemaUnique uniq = new XmlSchemaUnique ();
+
+ // if column of the constraint is hidden do not write the constraint.
+ bool isHidden = false;
+ foreach (DataColumn column in uqConst.Columns) {
+ if (column.ColumnMapping == MappingType.Hidden) {
+ isHidden = true;
+ break;
+ }
+ }
+
+ if (isHidden)
+ continue;
+
+ // if constaraint name do not exist in the hashtable we can use it.
+ if (!uniqueNames.ContainsKey (uqConst.ConstraintName)) {
+ uniq.Name = uqConst.ConstraintName;
+ }
+ // generate new constraint name for the XmlSchemaUnique element.
+ else {
+ uniq.Name = uqConst.Table.TableName + "_" + uqConst.ConstraintName;
+ attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.ConstraintName, XmlConstants.MsdataNamespace);
+ attrib.Value = uqConst.ConstraintName;
+ attrs.Add (attrib);
+ }
+ if (uqConst.IsPrimaryKey) {
+ attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.PrimaryKey, XmlConstants.MsdataNamespace);
+ attrib.Value = "true";
+ attrs.Add (attrib);
+ }
+
+ uniq.UnhandledAttributes = (XmlAttribute[])attrs.ToArray (typeof (XmlAttribute));
+
+ uniq.Selector = new XmlSchemaXPath();
+ uniq.Selector.XPath = ".//"+constraintPrefix + uqConst.Table.TableName;
+ XmlSchemaXPath field;
+ foreach (DataColumn column in uqConst.Columns) {
+ field = new XmlSchemaXPath();
+ 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);
+ }
+ }
+ }
+ return uniqueNames;
+ }
+
+ // Add the foriegn keys to the schema.
+ private void AddForeignKeys (Hashtable uniqueNames, XmlSchemaElement elem, string constraintPrefix, DataRelationCollection relations, XmlDocument doc)
+ {
+ if (relations == null) return;
+
+ foreach (DataRelation rel in relations) {
+
+ 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;
+ XmlSchemaKeyref keyRef = new XmlSchemaKeyref();
+ keyRef.Name = rel.RelationName;
+ ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
+ UniqueConstraint uqConst = rel.ParentKeyConstraint;
+
+ string concatName = rel.ParentTable.TableName + "_" + uqConst.ConstraintName;
+ // first try to find the concatenated name. If we didn't find it - use constraint name.
+ if (uniqueNames.ContainsKey (concatName)) {
+ keyRef.Refer = new XmlQualifiedName(concatName);
+ }
+ else {
+ keyRef.Refer = new XmlQualifiedName(uqConst.ConstraintName);
+ }
+
+ if (rel.Nested) {
+ attrib = doc.CreateAttribute (XmlConstants.MsdataPrefix, XmlConstants.IsNested, XmlConstants.MsdataNamespace);
+ attrib.Value = "true";
+ attrs.Add (attrib);
+ }
+
+ keyRef.Selector = new XmlSchemaXPath();
+ keyRef.Selector.XPath = ".//" + constraintPrefix + rel.ChildTable.TableName;
+ XmlSchemaXPath field;
+ foreach (DataColumn column in rel.ChildColumns) {
+ field = new XmlSchemaXPath();
+ 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);
+ }
+ }
+
+ private XmlSchemaElement GetTableSchema (XmlDocument doc, DataTable table, XmlSchema schemaToAdd, XmlNamespaceManager nsmgr)