e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
652 lines
26 KiB
C#
652 lines
26 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="XDRSchema.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
// <owner current="true" primary="true">[....]</owner>
|
|
// <owner current="true" primary="false">[....]</owner>
|
|
// <owner current="false" primary="false">[....]</owner>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Data {
|
|
using System;
|
|
using System.Xml;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Data.Common;
|
|
|
|
internal sealed class XDRSchema : XMLSchema {
|
|
internal String _schemaName;
|
|
internal String _schemaUri;
|
|
internal XmlElement _schemaRoot;
|
|
internal DataSet _ds;
|
|
private static char[] colonArray = new char[] {':'};
|
|
|
|
|
|
internal XDRSchema(DataSet ds, bool fInline) {
|
|
_schemaUri = String.Empty;
|
|
_schemaName = String.Empty;
|
|
_schemaRoot = null;
|
|
_ds = ds;
|
|
}
|
|
|
|
internal void LoadSchema(XmlElement schemaRoot, DataSet ds) {
|
|
if (schemaRoot == null)
|
|
return;
|
|
|
|
_schemaRoot = schemaRoot;
|
|
_ds = ds;
|
|
_schemaName = schemaRoot.GetAttribute(Keywords.NAME);
|
|
|
|
|
|
_schemaUri = "";
|
|
Debug.Assert(FEqualIdentity(schemaRoot, Keywords.XDR_SCHEMA, Keywords.XDRNS), "Illegal node");
|
|
|
|
// Get Locale and CaseSensitive properties
|
|
|
|
if (_schemaName == null || _schemaName.Length == 0)
|
|
_schemaName = "NewDataSet";
|
|
|
|
ds.Namespace = _schemaUri;
|
|
|
|
// Walk all the top level Element tags.
|
|
for (XmlNode n = schemaRoot.FirstChild; n != null; n = n.NextSibling) {
|
|
if (!(n is XmlElement))
|
|
continue;
|
|
|
|
XmlElement child = (XmlElement) n;
|
|
|
|
if (FEqualIdentity(child, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS)) {
|
|
HandleTable(child);
|
|
}
|
|
}
|
|
|
|
_schemaName = XmlConvert.DecodeName(_schemaName);
|
|
if (ds.Tables[_schemaName] == null)
|
|
ds.DataSetName = _schemaName;
|
|
|
|
}
|
|
|
|
internal XmlElement FindTypeNode(XmlElement node) {
|
|
string strType;
|
|
XmlNode vn;
|
|
XmlNode vnRoof;
|
|
|
|
Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_SCHEMA, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS),
|
|
"Invalid node type " + node.LocalName);
|
|
|
|
if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS))
|
|
return node;
|
|
|
|
strType = node.GetAttribute(Keywords.TYPE);
|
|
|
|
if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS)) {
|
|
if (strType == null || strType.Length == 0)
|
|
return null;
|
|
|
|
// Find an ELEMENTTYPE or ATTRIBUTETYPE with name=strType
|
|
vn = node.OwnerDocument.FirstChild;
|
|
vnRoof = node.OwnerDocument;
|
|
|
|
while (vn != vnRoof) {
|
|
if ((FEqualIdentity(vn, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) &&
|
|
FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) ||
|
|
(FEqualIdentity(vn, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS) &&
|
|
FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))) {
|
|
if (vn is XmlElement && ((XmlElement)vn).GetAttribute(Keywords.NAME) == strType)
|
|
return(XmlElement)vn;
|
|
}
|
|
|
|
// Move vn node
|
|
if (vn.FirstChild != null)
|
|
vn = vn.FirstChild;
|
|
else if (vn.NextSibling != null)
|
|
vn = vn.NextSibling;
|
|
else {
|
|
while (vn != vnRoof) {
|
|
vn = vn.ParentNode;
|
|
if (vn.NextSibling != null) {
|
|
vn = vn.NextSibling;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
internal bool IsTextOnlyContent(XmlElement node) {
|
|
Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS),
|
|
"Invalid node type " + node.LocalName);
|
|
|
|
string value = node.GetAttribute(Keywords.CONTENT);
|
|
if (value == null || value.Length == 0) {
|
|
string type = node.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS);
|
|
if (type != null && type.Length > 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
if (value == Keywords.EMPTY || value == Keywords.ELTONLY || value == Keywords.ELEMENTONLY || value == Keywords.MIXED)
|
|
return false;
|
|
if (value == Keywords.TEXTONLY)
|
|
return true;
|
|
|
|
throw ExceptionBuilder.InvalidAttributeValue("content", value);
|
|
}
|
|
|
|
internal bool IsXDRField(XmlElement node, XmlElement typeNode) {
|
|
int min = 1;
|
|
int max = 1;
|
|
|
|
if (!IsTextOnlyContent(typeNode))
|
|
return false;
|
|
|
|
for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) {
|
|
if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
|
|
FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
|
|
return false;
|
|
}
|
|
|
|
if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
|
|
GetMinMax(node, ref min, ref max);
|
|
if (max == -1 || max > 1)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
internal DataTable HandleTable(XmlElement node) {
|
|
XmlElement typeNode;
|
|
|
|
Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS), "Invalid node type");
|
|
|
|
|
|
// Figure out if this really is a table. If not, bail out.
|
|
typeNode = FindTypeNode(node);
|
|
|
|
string occurs = node.GetAttribute(Keywords.MINOCCURS);
|
|
|
|
if (occurs != null && occurs.Length > 0)
|
|
if ((Convert.ToInt32(occurs, CultureInfo.InvariantCulture)>1) && (typeNode==null)){
|
|
return InstantiateSimpleTable(_ds, node);
|
|
}
|
|
|
|
occurs = node.GetAttribute(Keywords.MAXOCCURS);
|
|
|
|
if (occurs != null && occurs.Length > 0)
|
|
if ((string.Compare(occurs, "1" , StringComparison.Ordinal) != 0) && (typeNode==null)){
|
|
return InstantiateSimpleTable(_ds, node);
|
|
}
|
|
|
|
|
|
if (typeNode == null)
|
|
return null;
|
|
|
|
if (IsXDRField(node, typeNode))
|
|
return null;
|
|
|
|
return InstantiateTable(_ds, node, typeNode);
|
|
}
|
|
|
|
private sealed class NameType : IComparable {
|
|
public String name;
|
|
public Type type;
|
|
public NameType(String n, Type t) {
|
|
name = n;
|
|
type = t;
|
|
}
|
|
public int CompareTo(object obj) { return String.Compare(name, (string)obj, StringComparison.Ordinal); }
|
|
};
|
|
// XDR spec: http://www.ltg.ed.ac.uk/~ht/XMLData-Reduced.htm
|
|
// http://webdata/newspecs/schema/xdr_dt_schema.xml
|
|
private static NameType[] mapNameTypeXdr = {
|
|
new NameType("bin.base64" , typeof(Byte[]) ), /* XDR */
|
|
new NameType("bin.hex" , typeof(Byte[]) ), /* XDR */
|
|
new NameType("boolean" , typeof(bool) ), /* XDR */
|
|
new NameType("byte" , typeof(SByte) ), /* XDR */
|
|
new NameType("char" , typeof(Char) ), /* XDR */
|
|
new NameType("date" , typeof(DateTime)), /* XDR */
|
|
new NameType("dateTime" , typeof(DateTime)), /* XDR */
|
|
new NameType("dateTime.tz" , typeof(DateTime)), /* XDR */
|
|
new NameType("entities" , typeof(string) ), /* XDR */
|
|
new NameType("entity" , typeof(string) ), /* XDR */
|
|
new NameType("enumeration" , typeof(string) ), /* XDR */
|
|
new NameType("fixed.14.4" , typeof(Decimal) ), /* XDR */
|
|
new NameType("float" , typeof(Double) ), /* XDR */
|
|
new NameType("i1" , typeof(SByte) ), /* XDR */
|
|
new NameType("i2" , typeof(Int16) ), /* XDR */
|
|
new NameType("i4" , typeof(Int32) ), /* XDR */
|
|
new NameType("i8" , typeof(Int64) ), /* XDR */
|
|
new NameType("id" , typeof(string) ), /* XDR */
|
|
new NameType("idref" , typeof(string) ), /* XDR */
|
|
new NameType("idrefs" , typeof(string) ), /* XDR */
|
|
new NameType("int" , typeof(Int32) ), /* XDR */
|
|
new NameType("nmtoken" , typeof(string) ), /* XDR */
|
|
new NameType("nmtokens" , typeof(string) ), /* XDR */
|
|
new NameType("notation" , typeof(string) ), /* XDR */
|
|
new NameType("number" , typeof(Decimal) ), /* XDR */
|
|
new NameType("r4" , typeof(Single) ), /* XDR */
|
|
new NameType("r8" , typeof(Double) ), /* XDR */
|
|
new NameType("string" , typeof(string) ), /* XDR */
|
|
new NameType("time" , typeof(DateTime)), /* XDR */
|
|
new NameType("time.tz" , typeof(DateTime)), /* XDR */
|
|
new NameType("ui1" , typeof(Byte) ), /* XDR */
|
|
new NameType("ui2" , typeof(UInt16) ), /* XDR */
|
|
new NameType("ui4" , typeof(UInt32) ), /* XDR */
|
|
new NameType("ui8" , typeof(UInt64) ), /* XDR */
|
|
new NameType("uri" , typeof(string) ), /* XDR */
|
|
new NameType("uuid" , typeof(Guid) ), /* XDR */
|
|
};
|
|
|
|
private static NameType FindNameType(string name) {
|
|
#if DEBUG
|
|
for(int i = 1; i < mapNameTypeXdr.Length; ++i) {
|
|
Debug.Assert((mapNameTypeXdr[i-1].CompareTo(mapNameTypeXdr[i].name)) < 0, "incorrect sorting");
|
|
}
|
|
#endif
|
|
int index = Array.BinarySearch(mapNameTypeXdr, name);
|
|
if (index < 0) {
|
|
#if DEBUG
|
|
// Let's check that we realy don't have this name:
|
|
foreach (NameType nt in mapNameTypeXdr) {
|
|
Debug.Assert(nt.name != name, "FindNameType('" + name + "') -- failed. Existed name not found");
|
|
}
|
|
#endif
|
|
throw ExceptionBuilder.UndefinedDatatype(name);
|
|
}
|
|
Debug.Assert(mapNameTypeXdr[index].name == name, "FindNameType('" + name + "') -- failed. Wrong name found");
|
|
return mapNameTypeXdr[index];
|
|
}
|
|
|
|
private static NameType enumerationNameType = FindNameType("enumeration");
|
|
|
|
private Type ParseDataType(string dt, string dtValues) {
|
|
string strType = dt;
|
|
string[] parts = dt.Split(colonArray); // ":"
|
|
|
|
if (parts.Length > 2) {
|
|
throw ExceptionBuilder.InvalidAttributeValue("type", dt);
|
|
}
|
|
else if (parts.Length == 2) {
|
|
//
|
|
strType = parts[1];
|
|
}
|
|
|
|
NameType nt = FindNameType(strType);
|
|
if (nt == enumerationNameType && (dtValues == null || dtValues.Length == 0))
|
|
throw ExceptionBuilder.MissingAttribute("type", Keywords.DT_VALUES);
|
|
return nt.type;
|
|
}
|
|
|
|
internal string GetInstanceName(XmlElement node) {
|
|
string instanceName;
|
|
|
|
if (FEqualIdentity(node, Keywords.XDR_ELEMENTTYPE, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ATTRIBUTETYPE, Keywords.XDRNS)) {
|
|
instanceName = node.GetAttribute(Keywords.NAME);
|
|
if (instanceName == null || instanceName.Length == 0) {
|
|
throw ExceptionBuilder.MissingAttribute("Element", Keywords.NAME);
|
|
}
|
|
}
|
|
else {
|
|
instanceName = node.GetAttribute(Keywords.TYPE);
|
|
if (instanceName == null || instanceName.Length == 0)
|
|
throw ExceptionBuilder.MissingAttribute("Element", Keywords.TYPE);
|
|
}
|
|
|
|
return instanceName;
|
|
}
|
|
|
|
internal void HandleColumn(XmlElement node, DataTable table) {
|
|
Debug.Assert(FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS) ||
|
|
FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS), "Illegal node type");
|
|
|
|
string instanceName;
|
|
string strName;
|
|
Type type;
|
|
string strType;
|
|
string strValues;
|
|
int minOccurs = 0;
|
|
int maxOccurs = 1;
|
|
string strDefault;
|
|
DataColumn column;
|
|
|
|
string strUse = node.GetAttribute(Keywords.USE);
|
|
|
|
|
|
|
|
// Get the name
|
|
if (node.Attributes.Count > 0) {
|
|
string strRef = node.GetAttribute(Keywords.REF);
|
|
|
|
if (strRef != null && strRef.Length>0)
|
|
return; //skip ref nodes. B2 item
|
|
|
|
strName = instanceName = GetInstanceName(node);
|
|
column = table.Columns[instanceName, _schemaUri];
|
|
if (column != null) {
|
|
if (column.ColumnMapping == MappingType.Attribute) {
|
|
if (FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS))
|
|
throw ExceptionBuilder.DuplicateDeclaration(strName);
|
|
}
|
|
else {
|
|
if (FEqualIdentity(node, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
|
|
throw ExceptionBuilder.DuplicateDeclaration(strName);
|
|
}
|
|
}
|
|
instanceName = GenUniqueColumnName(strName, table);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strName = instanceName = "";
|
|
}
|
|
|
|
// Now get the type
|
|
XmlElement typeNode = FindTypeNode(node);
|
|
|
|
SimpleType xsdType = null;
|
|
|
|
if (typeNode == null) {
|
|
strType = node.GetAttribute(Keywords.TYPE);
|
|
throw ExceptionBuilder.UndefinedDatatype(strType);
|
|
}
|
|
|
|
strType = typeNode.GetAttribute(Keywords.DT_TYPE, Keywords.DTNS);
|
|
strValues = typeNode.GetAttribute(Keywords.DT_VALUES, Keywords.DTNS);
|
|
if (strType == null || strType.Length == 0) {
|
|
strType = "";
|
|
type = typeof(string);
|
|
}
|
|
else {
|
|
type = ParseDataType(strType, strValues);
|
|
// HACK: temp work around special types
|
|
if (strType == "float") {
|
|
strType = "";
|
|
}
|
|
|
|
if (strType == "char") {
|
|
strType = "";
|
|
xsdType = SimpleType.CreateSimpleType(StorageType.Char, type);
|
|
}
|
|
|
|
|
|
if (strType == "enumeration") {
|
|
strType = "";
|
|
xsdType = SimpleType.CreateEnumeratedType(strValues);
|
|
}
|
|
|
|
if (strType == "bin.base64") {
|
|
strType = "";
|
|
xsdType = SimpleType.CreateByteArrayType("base64");
|
|
}
|
|
|
|
if (strType == "bin.hex") {
|
|
strType = "";
|
|
xsdType = SimpleType.CreateByteArrayType("hex");
|
|
}
|
|
|
|
}
|
|
|
|
bool isAttribute = FEqualIdentity(node, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS);
|
|
|
|
GetMinMax(node, isAttribute, ref minOccurs, ref maxOccurs);
|
|
|
|
strDefault = null;
|
|
|
|
// Does XDR has default?
|
|
strDefault = node.GetAttribute(Keywords.DEFAULT);
|
|
|
|
|
|
bool bNullable = false;
|
|
|
|
column = new DataColumn(XmlConvert.DecodeName(instanceName), type, null,
|
|
isAttribute ? MappingType.Attribute : MappingType.Element);
|
|
|
|
SetProperties(column, node.Attributes); // xmlschema.SetProperties will skipp setting expressions
|
|
column.XmlDataType = strType;
|
|
column.SimpleType = xsdType;
|
|
column.AllowDBNull = (minOccurs == 0) || bNullable;
|
|
column.Namespace = (isAttribute) ? String.Empty : _schemaUri;
|
|
// webdata 97925
|
|
// We will skip handling expression columns in SetProperties, so we need set the expressions here
|
|
if (node.Attributes != null) {
|
|
for (int i = 0; i < node.Attributes.Count; i++) {
|
|
if (node.Attributes[i].NamespaceURI == Keywords.MSDNS) {
|
|
if (node.Attributes[i].LocalName == "Expression"){
|
|
column.Expression = node.Attributes[i].Value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
String targetNamespace = node.GetAttribute(Keywords.TARGETNAMESPACE);
|
|
if (targetNamespace != null && targetNamespace.Length > 0)
|
|
column.Namespace = targetNamespace;
|
|
|
|
table.Columns.Add(column);
|
|
if (strDefault != null && strDefault.Length != 0)
|
|
try {
|
|
column.DefaultValue = SqlConvert.ChangeTypeForXML(strDefault, type);
|
|
}
|
|
catch (System.FormatException) {
|
|
|
|
throw ExceptionBuilder.CannotConvert(strDefault, type.FullName);
|
|
}
|
|
}
|
|
|
|
internal void GetMinMax(XmlElement elNode, ref int minOccurs, ref int maxOccurs) {
|
|
|
|
GetMinMax(elNode, false, ref minOccurs, ref maxOccurs);
|
|
|
|
}
|
|
|
|
internal void GetMinMax(XmlElement elNode, bool isAttribute, ref int minOccurs, ref int maxOccurs) {
|
|
|
|
string occurs = elNode.GetAttribute(Keywords.MINOCCURS);
|
|
if (occurs != null && occurs.Length > 0) {
|
|
try {
|
|
minOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
|
|
}
|
|
catch (Exception e) {
|
|
//
|
|
if (!ADP.IsCatchableExceptionType (e)) {
|
|
throw;
|
|
}
|
|
throw ExceptionBuilder.AttributeValues("minOccurs", "0", "1");
|
|
}
|
|
}
|
|
occurs = elNode.GetAttribute(Keywords.MAXOCCURS);
|
|
|
|
if (occurs != null && occurs.Length > 0) {
|
|
int bZeroOrMore = string.Compare(occurs, Keywords.STAR , StringComparison.Ordinal);
|
|
if (bZeroOrMore == 0) {
|
|
maxOccurs = -1;
|
|
}
|
|
else {
|
|
try {
|
|
maxOccurs = Int32.Parse(occurs, CultureInfo.InvariantCulture);
|
|
}
|
|
catch (Exception e) {
|
|
//
|
|
if (!ADP.IsCatchableExceptionType (e)) {
|
|
throw;
|
|
}
|
|
throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR);
|
|
}
|
|
if (maxOccurs != 1) {
|
|
throw ExceptionBuilder.AttributeValues("maxOccurs", "1", Keywords.STAR);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
internal void HandleTypeNode(XmlElement typeNode, DataTable table, ArrayList tableChildren)
|
|
{
|
|
DataTable tableChild;
|
|
|
|
for (XmlNode n = typeNode.FirstChild; n != null; n = n.NextSibling) {
|
|
|
|
if (!(n is XmlElement))
|
|
continue;
|
|
|
|
if (FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
|
|
|
|
|
|
tableChild = HandleTable((XmlElement) n);
|
|
if (tableChild != null) {
|
|
tableChildren.Add(tableChild);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (FEqualIdentity(n, Keywords.XDR_ATTRIBUTE, Keywords.XDRNS) ||
|
|
FEqualIdentity(n, Keywords.XDR_ELEMENT, Keywords.XDRNS)) {
|
|
HandleColumn((XmlElement) n, table);
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
internal DataTable InstantiateTable(DataSet dataSet, XmlElement node, XmlElement typeNode) {
|
|
string typeName = "";
|
|
XmlAttributeCollection attrs = node.Attributes;
|
|
DataTable table;
|
|
int minOccurs = 1;
|
|
int maxOccurs = 1;
|
|
string keys = null;
|
|
ArrayList tableChildren = new ArrayList();
|
|
|
|
|
|
|
|
if (attrs.Count > 0) {
|
|
typeName = GetInstanceName(node);
|
|
table = dataSet.Tables.GetTable(typeName, _schemaUri);
|
|
if (table != null) {
|
|
return table;
|
|
}
|
|
}
|
|
|
|
table = new DataTable(XmlConvert.DecodeName(typeName));
|
|
// fxcop: new DataTable should inherit the CaseSensitive, Locale from DataSet and possibly updating during SetProperties
|
|
|
|
table.Namespace = _schemaUri;
|
|
|
|
GetMinMax(node, ref minOccurs, ref maxOccurs);
|
|
table.MinOccurs = minOccurs;
|
|
table.MaxOccurs = maxOccurs;
|
|
|
|
_ds.Tables.Add(table);
|
|
|
|
HandleTypeNode(typeNode, table, tableChildren);
|
|
|
|
SetProperties(table, attrs);
|
|
|
|
// check to see if we fave unique constraint
|
|
|
|
if (keys != null) {
|
|
string[] list = keys.TrimEnd(null).Split(null);
|
|
int keyLength = list.Length;
|
|
|
|
DataColumn[] cols = new DataColumn[keyLength];
|
|
|
|
for (int i = 0; i < keyLength; i++) {
|
|
DataColumn col = table.Columns[list[i], _schemaUri];
|
|
if (col == null)
|
|
throw ExceptionBuilder.ElementTypeNotFound(list[i]);
|
|
cols[i] = col;
|
|
}
|
|
table.PrimaryKey = cols;
|
|
}
|
|
|
|
|
|
foreach(DataTable _tableChild in tableChildren) {
|
|
DataRelation relation = null;
|
|
|
|
DataRelationCollection childRelations = table.ChildRelations;
|
|
|
|
for (int j = 0; j < childRelations.Count; j++) {
|
|
if (!childRelations[j].Nested)
|
|
continue;
|
|
|
|
if (_tableChild == childRelations[j].ChildTable)
|
|
relation = childRelations[j];
|
|
}
|
|
|
|
if (relation!=null)
|
|
continue;
|
|
|
|
DataColumn parentKey = table.AddUniqueKey();
|
|
// foreign key in the child table
|
|
DataColumn childKey = _tableChild.AddForeignKey(parentKey);
|
|
// create relationship
|
|
// setup relationship between parent and this table
|
|
relation = new DataRelation(table.TableName + "_" + _tableChild.TableName, parentKey, childKey, true);
|
|
|
|
relation.CheckMultipleNested = false; // disable the check for multiple nested parent
|
|
|
|
relation.Nested = true;
|
|
_tableChild.DataSet.Relations.Add(relation);
|
|
relation.CheckMultipleNested = true; // enable the check for multiple nested parent
|
|
}
|
|
|
|
return table;
|
|
}
|
|
|
|
internal DataTable InstantiateSimpleTable(DataSet dataSet, XmlElement node) {
|
|
string typeName;
|
|
XmlAttributeCollection attrs = node.Attributes;
|
|
DataTable table;
|
|
int minOccurs = 1;
|
|
int maxOccurs = 1;
|
|
|
|
typeName = GetInstanceName(node);
|
|
table = dataSet.Tables.GetTable(typeName, _schemaUri);
|
|
if (table != null) {
|
|
throw ExceptionBuilder.DuplicateDeclaration(typeName);
|
|
}
|
|
String tbName = XmlConvert.DecodeName(typeName);
|
|
table = new DataTable(tbName);
|
|
// fxcop: new DataTable will either inherit the CaseSensitive, Locale from DataSet or be set during SetProperties
|
|
table.Namespace = _schemaUri;
|
|
GetMinMax(node, ref minOccurs, ref maxOccurs);
|
|
table.MinOccurs = minOccurs;
|
|
table.MaxOccurs = maxOccurs;
|
|
SetProperties(table, attrs);
|
|
table.repeatableElement = true;
|
|
|
|
HandleColumn((XmlElement) node, table);
|
|
|
|
table.Columns[0].ColumnName = tbName + "_Column";
|
|
_ds.Tables.Add(table);
|
|
|
|
|
|
return table;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|