public bool CreateConstraint;
}
+ internal class ConstraintStructure
+ {
+ public readonly string TableName;
+ public readonly string [] Columns;
+ public readonly bool [] IsAttribute;
+ public readonly string ConstraintName;
+ public readonly bool IsPrimaryKey;
+ public readonly string ReferName;
+ public readonly bool IsNested;
+ public readonly bool IsConstraintOnly;
+
+ public ConstraintStructure (string tname, string [] cols, bool [] isAttr, string cname, bool isPK, string refName, bool isNested, bool isConstraintOnly)
+ {
+ TableName = tname;
+ Columns = cols;
+ IsAttribute = isAttr;
+ ConstraintName = XmlHelper.Decode (cname);
+ IsPrimaryKey = isPK;
+ ReferName = refName;
+ IsNested = isNested;
+ IsConstraintOnly = isConstraintOnly;
+ }
+ }
+
internal class XmlSchemaDataImporter
{
static readonly XmlSchemaDatatype schemaIntegerType;
e.Name = "bar";
s.Items.Add (e);
s.Compile (null);
+#if NET_2_0
+ schemaIntegerType = ((XmlSchemaSimpleType) a.AttributeSchemaType).Datatype;
+ schemaDecimalType = ((XmlSchemaSimpleType) b.AttributeSchemaType).Datatype;
+ schemaAnyType = e.ElementSchemaType as XmlSchemaComplexType;
+#else
schemaIntegerType = a.AttributeType as XmlSchemaDatatype;
schemaDecimalType = b.AttributeType as XmlSchemaDatatype;
schemaAnyType = e.ElementType as XmlSchemaComplexType;
+#endif
}
#region Fields
DataSet dataset;
+ bool forDataSet;
XmlSchema schema;
ArrayList relations = new ArrayList ();
+ Hashtable reservedConstraints = new Hashtable ();
// such element that has an attribute msdata:IsDataSet="true"
XmlSchemaElement datasetElement;
// .ctor()
- public XmlSchemaDataImporter (DataSet dataset, XmlReader reader)
+ public XmlSchemaDataImporter (DataSet dataset, XmlReader reader, bool forDataSet)
{
this.dataset = dataset;
+ this.forDataSet = forDataSet;
dataset.DataSetName = "NewDataSet"; // Initialize always
schema = XmlSchema.Read (reader, null);
if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace)
dataset.DataSetName = schema.Id; // default. Overridable by "DataSet element"
dataset.Namespace = schema.TargetNamespace;
+ // Find dataset element
+ foreach (XmlSchemaObject obj in schema.Items) {
+ XmlSchemaElement el = obj as XmlSchemaElement;
+ if (el != null) {
+ if (datasetElement == null &&
+ IsDataSetElement (el))
+ datasetElement = el;
+#if NET_2_0
+ if (el.ElementSchemaType is XmlSchemaComplexType &&
+ el.ElementSchemaType != schemaAnyType)
+#else
+ if (el.ElementType is XmlSchemaComplexType &&
+ el.ElementType != schemaAnyType)
+#endif
+ targetElements.Add (obj);
+ }
+ }
+
+ // make reservation of identity constraints
+ if (datasetElement != null) {
+ // keys/uniques.
+ foreach (XmlSchemaObject obj in datasetElement.Constraints)
+ if (! (obj is XmlSchemaKeyref))
+ ReserveSelfIdentity ((XmlSchemaIdentityConstraint) obj);
+ // keyrefs.
+ foreach (XmlSchemaObject obj in datasetElement.Constraints)
+ if (obj is XmlSchemaKeyref)
+ ReserveRelationIdentity (datasetElement, (XmlSchemaKeyref) obj);
+ }
+
foreach (XmlSchemaObject obj in schema.Items) {
if (obj is XmlSchemaElement) {
XmlSchemaElement el = obj as XmlSchemaElement;
+#if NET_2_0
+ if (el.ElementSchemaType is XmlSchemaComplexType &&
+ el.ElementSchemaType != schemaAnyType)
+#else
if (el.ElementType is XmlSchemaComplexType &&
-el.ElementType != schemaAnyType)
+ el.ElementType != schemaAnyType)
+#endif
targetElements.Add (obj);
}
}
if (obj is XmlSchemaAnnotation)
HandleAnnotations ((XmlSchemaAnnotation) obj, false);
- foreach (RelationStructure rs in this.relations)
- dataset.Relations.Add (GenerateRelationship (rs));
-
if (datasetElement != null) {
// Handle constraints in the DataSet element. First keys.
foreach (XmlSchemaObject obj in datasetElement.Constraints)
if (! (obj is XmlSchemaKeyref))
- ProcessParentKey ((XmlSchemaIdentityConstraint) obj);
+ ProcessSelfIdentity (reservedConstraints [obj] as ConstraintStructure);
// Then keyrefs.
foreach (XmlSchemaObject obj in datasetElement.Constraints)
if (obj is XmlSchemaKeyref)
- ProcessReferenceKey (datasetElement, (XmlSchemaKeyref) obj);
+ ProcessRelationIdentity (datasetElement, reservedConstraints [obj] as ConstraintStructure);
}
+
+ foreach (RelationStructure rs in this.relations)
+ dataset.Relations.Add (GenerateRelationship (rs));
}
private bool IsDataSetElement (XmlSchemaElement el)
{
+ if (el.UnhandledAttributes != null) {
+ foreach (XmlAttribute attr in el.UnhandledAttributes) {
+ if (attr.LocalName == "IsDataSet" &&
+ attr.NamespaceURI == XmlConstants.MsdataNamespace) {
+ switch (attr.Value) {
+ case "true": // case sensitive
+ return true;
+ case "false":
+ break;
+ default:
+ throw new DataException (String.Format ("Value {0} is invalid for attribute 'IsDataSet'.", attr.Value));
+ }
+ }
+ }
+ }
+
if (schema.Elements.Count != 1)
return false;
if (!(el.SchemaType is XmlSchemaComplexType))
{
XmlSchemaElement el = p as XmlSchemaElement;
if (el != null) {
- XmlSchemaComplexType ct = el.ElementType as XmlSchemaComplexType;
+ XmlSchemaComplexType ct = null;
+#if NET_2_0
+ ct = el.ElementSchemaType as XmlSchemaComplexType;
+#else
+ ct = el.ElementType as XmlSchemaComplexType;
+#endif
if (ct == null || ct == schemaAnyType)
return true; // column element
if (ct.AttributeUses.Count > 0)
return false; // table element
- switch (ct.ContentType) {
- case XmlSchemaContentType.Empty:
- case XmlSchemaContentType.TextOnly:
+ if (ct.ContentType == XmlSchemaContentType.TextOnly)
return true; // column element
- default:
+ else
return false; // table element
- }
}
XmlSchemaGroupBase gb = p as XmlSchemaGroupBase;
for (int i = 0; i < gb.Items.Count; i++) {
if (dataset.Tables.Contains (el.QualifiedName.Name))
return;
- // Check if element is DataSet element
- if (el.UnhandledAttributes != null) {
- foreach (XmlAttribute attr in el.UnhandledAttributes) {
- if (attr.LocalName == "IsDataSet" &&
- attr.NamespaceURI == XmlConstants.MsdataNamespace) {
- switch (attr.Value) {
- case "true": // case sensitive
- ProcessDataSetElement (el);
- return;
- case "false":
- break;
- default:
- throw new DataException (String.Format ("Value {0} is invalid for attribute 'IsDataSet'.", attr.Value));
- }
- }
- }
- }
-
// If type is not complex, just skip this element
+#if NET_2_0
+ if (! (el.ElementSchemaType is XmlSchemaComplexType && el.ElementSchemaType != schemaAnyType))
+#else
if (! (el.ElementType is XmlSchemaComplexType && el.ElementType != schemaAnyType))
+#endif
return;
if (IsDataSetElement (el)) {
ProcessDataSetElement (el);
return;
}
+ else
+ dataset.Locale = CultureInfo.CurrentCulture;
// Register as a top-level element
topLevelElements.Add (el);
dataset.DataSetName = el.Name;
this.datasetElement = el;
- // Search for msdata:Locale attribute
+ // Search for locale attributes
+ bool useCurrent = false;
if (el.UnhandledAttributes != null) {
foreach (XmlAttribute attr in el.UnhandledAttributes) {
+#if NET_2_0
+ if (attr.LocalName == "UseCurrentLocale" &&
+ attr.NamespaceURI == XmlConstants.MsdataNamespace)
+ useCurrent = true;
+#endif
if (attr.LocalName == "Locale" &&
attr.NamespaceURI == XmlConstants.MsdataNamespace) {
CultureInfo ci = new CultureInfo (attr.Value);
}
}
}
+#if NET_2_0
+ if (!useCurrent && !dataset.LocaleSpecified) // then set current culture instance _explicitly_
+ dataset.Locale = CultureInfo.CurrentCulture;
+#endif
// Process content type particle (and create DataTable)
- XmlSchemaComplexType ct = el.ElementType as XmlSchemaComplexType;
+ XmlSchemaComplexType ct = null;
+#if NET_2_0
+ ct = el.ElementSchemaType as XmlSchemaComplexType;
+#else
+ ct = el.ElementType as XmlSchemaComplexType;
+#endif
XmlSchemaParticle p = ct != null ? ct.ContentTypeParticle : null;
if (p != null)
HandleDataSetContentTypeParticle (p);
{
XmlSchemaElement el = p as XmlSchemaElement;
if (el != null) {
+#if NET_2_0
+ if (el.ElementSchemaType is XmlSchemaComplexType && el.RefName != el.QualifiedName)
+#else
if (el.ElementType is XmlSchemaComplexType && el.RefName != el.QualifiedName)
+#endif
ProcessDataTableElement (el);
}
else if (p is XmlSchemaGroupBase) {
private void ProcessDataTableElement (XmlSchemaElement el)
{
- string tableName = XmlConvert.DecodeName (el.QualifiedName.Name);
+ string tableName = XmlHelper.Decode (el.QualifiedName.Name);
// If it is already registered, just ignore.
if (dataset.Tables.Contains (tableName))
return;
DataTable table = new DataTable (tableName);
table.Namespace = el.QualifiedName.Namespace;
+ TableStructure oldTable = currentTable;
currentTable = new TableStructure (table);
dataset.Tables.Add (table);
}
}
- // Handle complex type (NOTE: It is or should be
+ // Handle complex type (NOTE: It is (or should be)
// impossible the type is other than complex type).
- XmlSchemaComplexType ct = (XmlSchemaComplexType) el.ElementType;
+ XmlSchemaComplexType ct = null;
+#if NET_2_0
+ ct = (XmlSchemaComplexType) el.ElementSchemaType;
+#else
+ ct = (XmlSchemaComplexType) el.ElementType;
+#endif
// Handle attributes
foreach (DictionaryEntry de in ct.AttributeUses)
table.Columns.Add ((DataColumn) de.Value);
foreach (DataColumn dc in currentTable.NonOrdinalColumns)
table.Columns.Add (dc);
+
+ currentTable = oldTable;
}
private DataRelation GenerateRelationship (RelationStructure rs)
{
DataTable ptab = dataset.Tables [rs.ParentTableName];
DataTable ctab = dataset.Tables [rs.ChildTableName];
- DataColumn pcol = ptab.Columns [rs.ParentColumnName];
- DataColumn ccol = ctab.Columns [rs.ChildColumnName];
-
- if (ccol == null) {
- ccol = new DataColumn ();
- ccol.ColumnName = pcol.ColumnName;
- ccol.Namespace = String.Empty; // don't copy
- ccol.ColumnMapping = MappingType.Hidden;
- ccol.DataType = pcol.DataType;
- ctab.Columns.Add (ccol);
- }
- string name = rs.ExplicitName != null ? rs.ExplicitName : XmlConvert.DecodeName (ptab.TableName) + '_' + XmlConvert.DecodeName (ctab.TableName);
- DataRelation rel = new DataRelation (name, pcol, ccol, rs.CreateConstraint);
+ DataRelation rel ;
+ string name = rs.ExplicitName != null ? rs.ExplicitName : XmlHelper.Decode (ptab.TableName) + '_' + XmlHelper.Decode (ctab.TableName);
+
+ // Annotation Relations belonging to a DataSet can contain multiple colnames
+ // in parentkey and childkey.
+ if (datasetElement != null) {
+ String[] pcolnames = rs.ParentColumnName.Split (null);
+ String[] ccolnames = rs.ChildColumnName.Split (null);
+
+ DataColumn[] pcol = new DataColumn [pcolnames.Length];
+ for (int i=0; i<pcol.Length; ++i)
+ pcol [i] = ptab.Columns [XmlHelper.Decode (pcolnames [i])];
+
+ DataColumn[] ccol = new DataColumn [ccolnames.Length];
+ for (int i=0; i < ccol.Length; ++i) {
+ ccol [i] = ctab.Columns [XmlHelper.Decode (ccolnames [i])];
+ if (ccol [i] == null)
+ ccol [i] = CreateChildColumn (pcol [i], ctab);
+ }
+ rel = new DataRelation (name, pcol, ccol, rs.CreateConstraint);
+ } else {
+ DataColumn pcol = ptab.Columns [XmlHelper.Decode (rs.ParentColumnName)];
+ DataColumn ccol = ctab.Columns [XmlHelper.Decode (rs.ChildColumnName)];
+ if (ccol == null)
+ ccol = CreateChildColumn (pcol, ctab);
+ rel = new DataRelation (name, pcol, ccol, rs.CreateConstraint);
+ }
rel.Nested = rs.IsNested;
if (rs.CreateConstraint)
rel.ParentTable.PrimaryKey = rel.ParentColumns;
return rel;
}
+ private DataColumn CreateChildColumn (DataColumn parentColumn, DataTable childTable)
+ {
+ DataColumn col = childTable.Columns.Add (parentColumn.ColumnName,
+ parentColumn.DataType);
+ col.Namespace = String.Empty;
+ col.ColumnMapping = MappingType.Hidden;
+ return col;
+ }
+
private void ImportColumnGroupBase (XmlSchemaElement parent, XmlSchemaGroupBase gb)
{
foreach (XmlSchemaParticle p in gb.Items) {
XmlSchemaElement el = p as XmlSchemaElement;
if (el != null)
ImportColumnElement (parent, el);
- else
+ else if (p is XmlSchemaGroupBase)
ImportColumnGroupBase (parent, (XmlSchemaGroupBase) p);
+ // otherwise p is xs:any
}
}
DataColumn col = new DataColumn ();
col.ColumnName = attr.QualifiedName.Name;
col.Namespace = attr.QualifiedName.Namespace;
- XmlSchemaDatatype dt = GetSchemaPrimitiveType (attr.AttributeType);
+ XmlSchemaDatatype dt = null;
+#if NET_2_0
+ dt = GetSchemaPrimitiveType (((XmlSchemaSimpleType) attr.AttributeSchemaType).Datatype);
+#else
+ dt = GetSchemaPrimitiveType (attr.AttributeType);
+#endif
// This complicated check comes from the fact that
// MS.NET fails to map System.Object to anyType (that
// will cause ReadTypedObject() fail on XmlValidatingReader).
if (attr.Use == XmlSchemaUse.Required)
col.AllowDBNull = false;
+#if NET_2_0
+ FillFacet (col, attr.AttributeSchemaType as XmlSchemaSimpleType);
+#else
FillFacet (col, attr.AttributeType as XmlSchemaSimpleType);
+#endif
// Call this method after filling the name
ImportColumnMetaInfo (attr, attr.QualifiedName, col);
col.DefaultValue = GetElementDefaultValue (el);
col.AllowDBNull = (el.MinOccurs == 0);
+#if NET_2_0
+ if (el.ElementSchemaType is XmlSchemaComplexType && el.ElementSchemaType != schemaAnyType)
+#else
if (el.ElementType is XmlSchemaComplexType && el.ElementType != schemaAnyType)
+#endif
FillDataColumnComplexElement (parent, el, col);
else if (el.MaxOccurs != 1)
FillDataColumnRepeatedSimpleElement (parent, el, col);
// common process for element and attribute
private void ImportColumnMetaInfo (XmlSchemaAnnotated obj, XmlQualifiedName name, DataColumn col)
{
- int ordinal = -1;
if (obj.UnhandledAttributes != null) {
foreach (XmlAttribute attr in obj.UnhandledAttributes) {
if (attr.NamespaceURI != XmlConstants.MsdataNamespace)
case XmlConstants.AutoIncrementSeed:
col.AutoIncrementSeed = int.Parse (attr.Value);
break;
+ case XmlConstants.AutoIncrementStep:
+ col.AutoIncrementStep = int.Parse (attr.Value);
+ break;
case XmlConstants.ReadOnly:
col.ReadOnly = XmlConvert.ToBoolean (attr.Value);
break;
case XmlConstants.Ordinal:
- ordinal = int.Parse (attr.Value);
+ int ordinal = int.Parse (attr.Value);
break;
}
}
if (targetElements.Contains (el))
return; // do nothing
- string elName = XmlConvert.DecodeName (el.QualifiedName.Name);
+ string elName = XmlHelper.Decode (el.QualifiedName.Name);
if (elName == dataset.DataSetName)
// Well, why it is ArgumentException :-?
throw new ArgumentException ("Nested element must not have the same name as DataSet's name.");
if (el.Annotation != null)
HandleAnnotations (el.Annotation, true);
- else {
+ // If xsd:keyref xsd:key for this table exists, then don't add
+ // relation here manually.
+ else if (!DataSetDefinesKey (elName)) {
AddParentKeyColumn (parent, el, col);
- DataColumn pkey = currentTable.PrimaryKey;
RelationStructure rel = new RelationStructure ();
- rel.ParentTableName = XmlConvert.DecodeName (parent.QualifiedName.Name);
+ rel.ParentTableName = XmlHelper.Decode (parent.QualifiedName.Name);
rel.ChildTableName = elName;
- rel.ParentColumnName = pkey.ColumnName;
- rel.ChildColumnName = pkey.ColumnName;
+ rel.ParentColumnName = col.ColumnName;
+ rel.ChildColumnName = col.ColumnName;
rel.CreateConstraint = true;
rel.IsNested = true;
relations.Add (rel);
// If the element is not referenced one, the element will be handled later.
if (el.RefName == XmlQualifiedName.Empty)
- targetElements.Add (el);
+ ProcessDataTableElement (el);
}
+ private bool DataSetDefinesKey (string name)
+ {
+ foreach (ConstraintStructure c in reservedConstraints.Values)
+ if (c.TableName == name && (c.IsPrimaryKey || c.IsNested))
+ return true;
+ return false;
+ }
+
private void AddParentKeyColumn (XmlSchemaElement parent, XmlSchemaElement el, DataColumn col)
{
if (currentTable.PrimaryKey != null)
return;
// check name identity
- string name = XmlConvert.DecodeName (parent.QualifiedName.Name) + "_Id";
- if (currentTable.ContainsColumn (name))
- throw new DataException (String.Format ("There is already a column that has the same name: {0}", name));
+ string name = XmlHelper.Decode (parent.QualifiedName.Name) + "_Id";
+ int count = 0;
+ while (currentTable.ContainsColumn (name))
+ name = String.Format ("{0}_{1}", name, count++);
// check existing primary key
if (currentTable.Table.PrimaryKey.Length > 0)
throw new DataException (String.Format ("There is already primary key columns in the table \"{0}\".", currentTable.Table.TableName));
col.ColumnMapping = MappingType.Hidden;
col.Namespace = parent.QualifiedName.Namespace;
col.DataType = typeof (int);
- col.Unique = true;
col.AutoIncrement = true;
col.AllowDBNull = false;
AddParentKeyColumn (parent, el, col);
DataColumn pkey = currentTable.PrimaryKey;
- string elName = XmlConvert.DecodeName (el.QualifiedName.Name);
- string parentName = XmlConvert.DecodeName (parent.QualifiedName.Name);
+ string elName = XmlHelper.Decode (el.QualifiedName.Name);
+ string parentName = XmlHelper.Decode (parent.QualifiedName.Name);
DataTable dt = new DataTable ();
dt.TableName = elName;
cc2.Namespace = el.QualifiedName.Namespace;
cc2.ColumnMapping = MappingType.SimpleContent;
cc2.AllowDBNull = false;
+#if NET_2_0
+ cc2.DataType = ConvertDatatype (GetSchemaPrimitiveType (el.ElementSchemaType));
+#else
cc2.DataType = ConvertDatatype (GetSchemaPrimitiveType (el.ElementType));
+#endif
dt.Columns.Add (cc2);
dt.Columns.Add (cc);
private void FillDataColumnSimpleElement (XmlSchemaElement el, DataColumn col)
{
- col.ColumnName = XmlConvert.DecodeName (el.QualifiedName.Name);
+ col.ColumnName = XmlHelper.Decode (el.QualifiedName.Name);
col.Namespace = el.QualifiedName.Namespace;
col.ColumnMapping = MappingType.Element;
+#if NET_2_0
+ col.DataType = ConvertDatatype (GetSchemaPrimitiveType (el.ElementSchemaType));
+ FillFacet (col, el.ElementSchemaType as XmlSchemaSimpleType);
+#else
col.DataType = ConvertDatatype (GetSchemaPrimitiveType (el.ElementType));
FillFacet (col, el.ElementType as XmlSchemaSimpleType);
+#endif
ImportColumnMetaInfo (el, el.QualifiedName, col);
if (index > 0)
tableName = tableName.Substring (index + 1);
- return XmlConvert.DecodeName (tableName);
+ return XmlHelper.Decode (tableName);
}
- private void ProcessParentKey (XmlSchemaIdentityConstraint ic)
+ private void ReserveSelfIdentity (XmlSchemaIdentityConstraint ic)
{
- // Basic concept came from XmlSchemaMapper.cs
-
string tableName = GetSelectorTarget (ic.Selector.XPath);
-
- DataTable dt = dataset.Tables [tableName];
- if (dt == null)
- throw new DataException (String.Format ("Invalid XPath selection inside selector. Cannot find: {0}", tableName));
- DataColumn [] cols = new DataColumn [ic.Fields.Count];
+ string [] cols = new string [ic.Fields.Count];
+ bool [] isAttrSpec = new bool [cols.Length];
+
int i = 0;
foreach (XmlSchemaXPath Field in ic.Fields) {
string colName = Field.XPath;
else if (isAttr)
colName = colName.Substring (1);
- colName = XmlConvert.DecodeName (colName);
- DataColumn col = dt.Columns [colName];
- if (col == null)
- throw new DataException (String.Format ("Invalid XPath selection inside field. Cannot find: {0}", tableName));
- if (isAttr && col.ColumnMapping != MappingType.Attribute)
- throw new DataException ("The XPath specified attribute field, but mapping type is not attribute.");
- if (!isAttr && col.ColumnMapping != MappingType.Element)
- throw new DataException ("The XPath specified simple element field, but mapping type is not simple element.");
-
- cols [i] = dt.Columns [colName];
+ colName = XmlHelper.Decode (colName);
+ cols [i] = colName;
+ isAttrSpec [i] = isAttr;
i++;
}
}
}
}
- UniqueConstraint c = new UniqueConstraint (constraintName, cols, isPK);
- dt.Constraints.Add (c);
+ reservedConstraints.Add (ic,
+ new ConstraintStructure (tableName, cols,
+ isAttrSpec, constraintName, isPK, null, false, false));
}
- private void ProcessReferenceKey (XmlSchemaElement element, XmlSchemaKeyref keyref)
+ private void ProcessSelfIdentity (ConstraintStructure c)
{
// Basic concept came from XmlSchemaMapper.cs
- string tableName = GetSelectorTarget (keyref.Selector.XPath);
-
- DataColumn [] cols;
+ string tableName = c.TableName;
+
DataTable dt = dataset.Tables [tableName];
- if (dt == null)
- throw new DataException (String.Format ("Invalid XPath selection inside selector. Cannot find: {0}", tableName));
+ if (dt == null) {
+ if (forDataSet)
+ throw new DataException (String.Format ("Invalid XPath selection inside selector. Cannot find: {0}", tableName));
+ else
+ // nonexistent table name. .NET ignores it for DataTable.ReadXmlSchema().
+ return;
+ }
+
+ DataColumn [] cols = new DataColumn [c.Columns.Length];
+ for (int i = 0; i < cols.Length; i++) {
+ string colName = c.Columns [i];
+ bool isAttr = c.IsAttribute [i];
+ DataColumn col = dt.Columns [colName];
+ if (col == null)
+ throw new DataException (String.Format ("Invalid XPath selection inside field. Cannot find: {0}", tableName));
+ if (isAttr && col.ColumnMapping != MappingType.Attribute)
+ throw new DataException ("The XPath specified attribute field, but mapping type is not attribute.");
+ if (!isAttr && col.ColumnMapping != MappingType.Element)
+ throw new DataException ("The XPath specified simple element field, but mapping type is not simple element.");
+
+ cols [i] = dt.Columns [colName];
+ }
+
+ bool isPK = c.IsPrimaryKey;
+ string constraintName = c.ConstraintName;
+ dt.Constraints.Add (new UniqueConstraint (
+ constraintName, cols, isPK));
+ }
+
+ private void ReserveRelationIdentity (XmlSchemaElement element, XmlSchemaKeyref keyref)
+ {
+ // Basic concept came from XmlSchemaMapper.cs
- cols = new DataColumn [keyref.Fields.Count];
+ string tableName = GetSelectorTarget (keyref.Selector.XPath);
+
+ string [] cols = new string [keyref.Fields.Count];
+ bool [] isAttrSpec = new bool [cols.Length];
int i = 0;
foreach (XmlSchemaXPath Field in keyref.Fields) {
string colName = Field.XPath;
else if (isAttr)
colName = colName.Substring (1);
- colName = XmlConvert.DecodeName (colName);
+ colName = XmlHelper.Decode (colName);
+ cols [i] = colName;
+ isAttrSpec [i] = isAttr;
+ i++;
+ }
+ string constraintName = keyref.Name;
+ bool isNested = false;
+ bool isConstraintOnly = false;
+ if (keyref.UnhandledAttributes != null) {
+ foreach (XmlAttribute attr in keyref.UnhandledAttributes) {
+ if (attr.NamespaceURI != XmlConstants.MsdataNamespace)
+ continue;
+ switch (attr.LocalName) {
+ case XmlConstants.ConstraintName:
+ constraintName = attr.Value;
+ break;
+ case XmlConstants.IsNested:
+ if (attr.Value == "true")
+ isNested = true;
+ break;
+ case XmlConstants.ConstraintOnly:
+ if (attr.Value == "true")
+ isConstraintOnly = true;
+ break;
+ }
+ }
+ }
+
+ reservedConstraints.Add (keyref, new ConstraintStructure (
+ tableName, cols, isAttrSpec, constraintName,
+ false, keyref.Refer.Name, isNested, isConstraintOnly));
+ }
+
+ private void ProcessRelationIdentity (XmlSchemaElement element, ConstraintStructure c)
+ {
+ // Basic concept came from XmlSchemaMapper.cs
+
+ string tableName = c.TableName;
+
+ DataColumn [] cols;
+ DataTable dt = dataset.Tables [tableName];
+ if (dt == null)
+ throw new DataException (String.Format ("Invalid XPath selection inside selector. Cannot find: {0}", tableName));
+
+ cols = new DataColumn [c.Columns.Length];
+ for (int i = 0; i < cols.Length; i++) {
+ string colName = c.Columns [i];
+ bool isAttr = c.IsAttribute [i];
DataColumn col = dt.Columns [colName];
if (isAttr && col.ColumnMapping != MappingType.Attribute)
throw new DataException ("The XPath specified attribute field, but mapping type is not attribute.");
if (!isAttr && col.ColumnMapping != MappingType.Element)
throw new DataException ("The XPath specified simple element field, but mapping type is not simple element.");
cols [i] = col;
- i++;
}
- string name = keyref.Refer.Name;
+ string name = c.ReferName;
// get the unique constraint for the releation
UniqueConstraint uniq = FindConstraint (name, element);
// generate the FK.
- ForeignKeyConstraint fkc = new ForeignKeyConstraint(keyref.Name, uniq.Columns, cols);
+ ForeignKeyConstraint fkc = new ForeignKeyConstraint(c.ConstraintName, uniq.Columns, cols);
dt.Constraints.Add (fkc);
- // generate the relation.
- DataRelation rel = new DataRelation (keyref.Name, uniq.Columns, cols, false);
- if (keyref.UnhandledAttributes != null) {
- foreach (XmlAttribute attr in keyref.UnhandledAttributes)
- if (attr.LocalName == "IsNested" && attr.Value == "true" && attr.NamespaceURI == XmlConstants.MsdataNamespace)
- rel.Nested = true;
- }
- rel.SetParentKeyConstraint (uniq);
- rel.SetChildKeyConstraint (fkc);
- dataset.Relations.Add (rel);
+ if (!c.IsConstraintOnly) {
+ // generate the relation.
+ DataRelation rel = new DataRelation (c.ConstraintName, uniq.Columns, cols, true);
+ rel.Nested = c.IsNested;
+ rel.SetParentKeyConstraint (uniq);
+ rel.SetChildKeyConstraint (fkc);
+
+ dataset.Relations.Add (rel);
+ }
}
// get the unique constraint for the relation.
string fkn = el.GetAttribute ("childkey", XmlConstants.MsdataNamespace);
RelationStructure rel = new RelationStructure ();
- rel.ExplicitName = name;
- rel.ParentTableName = ptn;
- rel.ChildTableName = ctn;
+ rel.ExplicitName = XmlHelper.Decode (name);
+ rel.ParentTableName = XmlHelper.Decode (ptn);
+ rel.ChildTableName = XmlHelper.Decode (ctn);
+ // ColumnNames will be decoded wherever they are used as they can
+ // contain 'space' separated list of column-names.
rel.ParentColumnName = pkn;
rel.ChildColumnName = fkn;
rel.IsNested = nested;