| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600 |
- //
- // XmlSchemaDataImporter.cs
- //
- // Author:
- // Atsushi Enomoto <[email protected]>
- //
- // (C)2004 Novell Inc.
- //
- //
- // ***** The design note became somewhat obsolete. Should be rewritten. *****
- //
- // * Design Notes
- //
- // ** Abstract
- //
- // This class is used to import an XML Schema into a DataSet schema.
- //
- // Only XmlReader is acceptable as the input to the class.
- // This class is not expected to read XML Schema multi time.
- //
- // ** Targetable Schema Components
- //
- // Only global global elements that hold complex type are converted
- // into a table.
- // <del>
- // The components of the type of the element are subsequently converted
- // into a table, BUT there is an exception. As for "DataSet elements",
- // the type is just ignored (see "DataSet Element definition" below).
- // </del><ins>
- // The components of the type of the element are subsequently converted
- // into a table. As for "DataSet elements", its complex type is also
- // handled.
- // </ins>
- //
- // Unused complex types are never be converted.
- //
- // Global simple types and global attributes are never converted.
- // They cannot be a table.
- // Local complex types are also converted into a table.
- //
- // Local elements are converted into either a table or a column in
- // the "context DataTable". Simple-typed element is not always converted
- // into a DataColumn; if maxOccurs > 1, it will be converted as a table.
- //
- // ** Name Convention
- //
- // Ignore this section. Microsoft.NET was buggy enough to confuse
- // against these name conflicts.
- //
- // Since local complex types are anonymous, we have to name for each
- // component. Thus, and since complex types and elements can have the
- // same name each other, we have to manage a table for mappings from
- // a name to a component. The names must be also used in DataRelation
- // definitions correctly.
- //
- // ** DataSet element definition
- //
- // "DataSet element" is 1) such element that has an attribute
- // msdata:IsDataSet (where prefix "msdata" is bound to
- // urn:schemas-microsoft-com:xml-msdata), or 2) the only one
- // element definition in the schema.
- //
- // There is another complicated rule. 1) If there is only one element EL
- // in the schema, and 2) if the type of EL is complex named CT, and 3)
- // the content of the CT is a group base, and 4) the group base contains
- // an element EL2, and finally 5) if EL2 is complex, THEN the element is
- // the DataSet element.
- //
- // Only the first global element that matches the condition above is
- // regarded as DataSet element (by necessary design or just a bug?)
- // instead of handling as an error.
- //
- // All global elements are considered as an alternative in the dataset
- // element.
- //
- // For local elements, msdata:IsDataSet are just ignored.
- //
- // ** Importing Complex Types as Columns
- //
- // When an xs:element is going to be mapped, its complex type (remember
- // that only complex-typed elements are targettable) are expanded to
- // DataColumn.
- //
- // DataColumn has a property MappingType that shows whether this column
- // came from attribute or element.
- //
- // [Question: How about MappingType.Simple? How is it used?]
- //
- // Additionally, for particle elements, it might also create another
- // DataTable (but for the particle elements in context DataTable, it
- // will create an index to the new table).
- //
- // For group base particles (XmlSchemaGroupBase; sequence, choice, all)
- // each component in those groups are mapped to a column. Even if you
- // import "choice" or "all" components, DataSet.WriteXmlSchema() will
- // output them just as a "sequence".
- //
- // Columns cannot be added directly to current context DataTable; they
- // need to be added after processing all the columns, because they may
- // have msdata:Ordinal attribute that specifies the order of the columns
- // in the DataTable.
- //
- // "Nested elements" are not allowed. (Clarification required?)
- //
- // ** Identity Constraints and DataRelations
- //
- // *** DataRelations from element identity constraints
- //
- // Only constraints on "DataSet element" is considered. All other
- // constraint definitions are ignored. Note that it is DataSet that has
- // the property Relations (of type DataRelationCollection).
- //
- // xs:key and xs:unique are handled as the same (then both will be
- // serialized as xs:unique).
- //
- // The XPath expressions in the constraints are strictly limited; they
- // are expected to be expandable enough to be mappable for each
- //
- // * selector to "any_valid_XPath/is/OK/blah"
- // where "blah" is one of the DataTable name. It looks that
- // only the last QName section is significant and any heading
- // XPath step is OK (even if the mapped node does not exist).
- // * field to QName that is mapped to DataColumn in the DataTable
- // (even ./QName is not allowed)
- //
- // *** DataRelations from annotations
- //
- // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/_mapping_relationship_specified_for_nested_elements.asp and http://msdn.microsoft.com/library/en-us/cpguide/html/_specifying_relationship_between_elements_with_no_nesting.asp
- //
- // ** Informative References
- //
- // Generating DataSet Relational Structure from XML Schema (XSD)
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/_generating_dataset_relational_structure_from_xsd.asp
- //
- //
- // 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.Data;
- using System.Data.Common;
- using System.Globalization;
- using System.Xml;
- using System.Xml.Schema;
- namespace System.Data
- {
- internal class TableStructureCollection : CollectionBase
- {
- public void Add (TableStructure table)
- {
- List.Add (table);
- }
- public TableStructure this [int i] {
- get { return List [i] as TableStructure; }
- }
- public TableStructure this [string name] {
- get {
- foreach (TableStructure ts in List)
- if (ts.Table.TableName == name)
- return ts;
- return null;
- }
- }
- }
- internal class RelationStructureCollection : CollectionBase
- {
- public void Add (RelationStructure rel)
- {
- List.Add (rel);
- }
- public RelationStructure this [int i] {
- get { return List [i] as RelationStructure; }
- }
- public RelationStructure this [string parent, string child] {
- get {
- foreach (RelationStructure rel in List)
- if (rel.ParentTableName == parent && rel.ChildTableName == child)
- return rel;
- return null;
- }
- }
- }
-
- internal class TableStructure
- {
- public TableStructure (DataTable table)
- {
- this.Table = table;
- }
- // The columns and orders which will be added to the context
- // table (See design notes; Because of the ordinal problem)
- public DataTable Table;
- public Hashtable OrdinalColumns = new Hashtable ();
- public ArrayList NonOrdinalColumns = new ArrayList ();
- public DataColumn PrimaryKey;
- public bool ContainsColumn (string name)
- {
- foreach (DataColumn col in NonOrdinalColumns)
- if (col.ColumnName == name)
- return true;
- foreach (DataColumn col in OrdinalColumns.Keys)
- if (col.ColumnName == name)
- return true;
- return false;
- }
- }
- internal class RelationStructure
- {
- public string ExplicitName;
- public string ParentTableName;
- public string ChildTableName;
- public string ParentColumnName;
- public string ChildColumnName;
- public bool IsNested;
- 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;
- static readonly XmlSchemaDatatype schemaDecimalType;
- static readonly XmlSchemaComplexType schemaAnyType;
- static XmlSchemaDataImporter ()
- {
- XmlSchema s = new XmlSchema ();
- XmlSchemaAttribute a = new XmlSchemaAttribute ();
- a.Name = "foo";
- a.SchemaTypeName = new XmlQualifiedName ("integer", XmlSchema.Namespace);
- s.Items.Add (a);
- XmlSchemaAttribute b = new XmlSchemaAttribute ();
- b.Name = "bar";
- b.SchemaTypeName = new XmlQualifiedName ("decimal", XmlSchema.Namespace);
- s.Items.Add (b);
- XmlSchemaElement e = new XmlSchemaElement ();
- 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;
- // choice alternatives in the "dataset element"
- ArrayList topLevelElements = new ArrayList ();
- // import target elements
- ArrayList targetElements = new ArrayList ();
- TableStructure currentTable;
-
- #if NET_2_0
- // TODO: Do we need a collection here?
- TableAdapterSchemaInfo currentAdapter;
- #endif
- #endregion
- // .ctor()
- 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)
- reader.ReadEndElement ();
- schema.Compile (null);
- }
- #if NET_2_0
- // properties
- internal TableAdapterSchemaInfo CurrentAdapter {
- get { return currentAdapter; }
- }
- #endif
-
- // methods
- public void Process ()
- {
- if (schema.Id != null)
- 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)
- #endif
- targetElements.Add (obj);
- }
- }
- // This collection will grow up while processing elements.
- int globalElementCount = targetElements.Count;
- for (int i = 0; i < globalElementCount; i++)
- ProcessGlobalElement ((XmlSchemaElement) targetElements [i]);
- // Rest are local elements.
- for (int i = globalElementCount; i < targetElements.Count; i++)
- ProcessDataTableElement ((XmlSchemaElement) targetElements [i]);
- // Handle relation definitions written as xs:annotation.
- // See detail: http://msdn.microsoft.com/library/shared/happyUrl/fnf_msdn.asp?Redirect=%22http://msdn.microsoft.com/404/default.asp%22
- foreach (XmlSchemaObject obj in schema.Items)
- if (obj is XmlSchemaAnnotation)
- HandleAnnotations ((XmlSchemaAnnotation) obj, false);
- if (datasetElement != null) {
- // Handle constraints in the DataSet element. First keys.
- foreach (XmlSchemaObject obj in datasetElement.Constraints)
- if (! (obj is XmlSchemaKeyref))
- ProcessSelfIdentity (reservedConstraints [obj] as ConstraintStructure);
- // Then keyrefs.
- foreach (XmlSchemaObject obj in datasetElement.Constraints)
- if (obj is XmlSchemaKeyref)
- 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))
- return false;
- XmlSchemaComplexType ct = (XmlSchemaComplexType) el.SchemaType;
- if (ct.AttributeUses.Count > 0)
- return false;
- XmlSchemaGroupBase gb = ct.ContentTypeParticle as XmlSchemaGroupBase;
- if (gb == null || gb.Items.Count == 0)
- return false;
- foreach (XmlSchemaParticle p in gb.Items) {
- if (ContainsColumn (p))
- return false;
- }
- return true;
- }
- private bool ContainsColumn (XmlSchemaParticle p)
- {
- XmlSchemaElement el = p as XmlSchemaElement;
- if (el != null) {
- 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
- if (ct.ContentType == XmlSchemaContentType.TextOnly)
- return true; // column element
- else
- return false; // table element
- }
- XmlSchemaGroupBase gb = p as XmlSchemaGroupBase;
- for (int i = 0; i < gb.Items.Count; i++) {
- if (ContainsColumn ((XmlSchemaParticle) gb.Items [i]))
- return true;
- }
- return false;
- }
- private void ProcessGlobalElement (XmlSchemaElement el)
- {
- // If it is already registered (by resolving reference
- // in previously-imported elements), just ignore.
- if (dataset.Tables.Contains (el.QualifiedName.Name))
- return;
- // 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);
- // Create DataTable for this element
- ProcessDataTableElement (el);
- }
- private void ProcessDataSetElement (XmlSchemaElement el)
- {
- dataset.DataSetName = el.Name;
- this.datasetElement = el;
- // 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);
- dataset.Locale = ci;
- }
- }
- }
- #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 = 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);
- }
- private void HandleDataSetContentTypeParticle (XmlSchemaParticle 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) {
- foreach (XmlSchemaParticle pc in ((XmlSchemaGroupBase) p).Items)
- HandleDataSetContentTypeParticle (pc);
- }
- }
- private void ProcessDataTableElement (XmlSchemaElement el)
- {
- 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);
- // Find Locale
- if (el.UnhandledAttributes != null) {
- foreach (XmlAttribute attr in el.UnhandledAttributes) {
- if (attr.LocalName == "Locale" &&
- attr.NamespaceURI == XmlConstants.MsdataNamespace)
- table.Locale = new CultureInfo (attr.Value);
- }
- }
- // Handle complex type (NOTE: It is (or should be)
- // impossible the type is other than complex type).
- 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)
- ImportColumnAttribute ((XmlSchemaAttribute) de.Value);
- // Handle content type particle
- if (ct.ContentTypeParticle is XmlSchemaElement)
- ImportColumnElement (el, (XmlSchemaElement) ct.ContentTypeParticle);
- else if (ct.ContentTypeParticle is XmlSchemaGroupBase)
- ImportColumnGroupBase (el, (XmlSchemaGroupBase) ct.ContentTypeParticle);
- // else if null then do nothing.
- // Handle simple content
- switch (ct.ContentType) {
- case XmlSchemaContentType.TextOnly:
- // case XmlSchemaContentType.Mixed:
- // LAMESPEC: When reading from XML Schema, it maps to "_text", while on the data inference, it is mapped to "_Text" (case ignorant).
- string simpleName = el.QualifiedName.Name + "_text";
- DataColumn simple = new DataColumn (simpleName);
- simple.Namespace = el.QualifiedName.Namespace;
- simple.AllowDBNull = (el.MinOccurs == 0);
- simple.ColumnMapping = MappingType.SimpleContent;
- simple.DataType = ConvertDatatype (ct.Datatype);
- currentTable.NonOrdinalColumns.Add (simple);
- break;
- }
- // add columns to the table in specified order
- // (by msdata:Ordinal attributes)
- SortedList sd = new SortedList ();
- foreach (DictionaryEntry de in currentTable.OrdinalColumns)
- sd.Add (de.Value, de.Key);
- foreach (DictionaryEntry de in sd)
- 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];
- 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 if (p is XmlSchemaGroupBase)
- ImportColumnGroupBase (parent, (XmlSchemaGroupBase) p);
- // otherwise p is xs:any
- }
- }
- private XmlSchemaDatatype GetSchemaPrimitiveType (object type)
- {
- if (type is XmlSchemaComplexType)
- return null; // It came here, so that maybe it is xs:anyType
- XmlSchemaDatatype dt = type as XmlSchemaDatatype;
- if (dt == null && type != null)
- dt = ((XmlSchemaSimpleType) type).Datatype;
- return dt;
- }
- // Note that this column might be Hidden
- private void ImportColumnAttribute (XmlSchemaAttribute attr)
- {
- DataColumn col = new DataColumn ();
- col.ColumnName = attr.QualifiedName.Name;
- col.Namespace = attr.QualifiedName.Namespace;
- 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).
- // ONLY In DataSet context, we set System.String for
- // simple ur-type.
- col.DataType = ConvertDatatype (dt);
- if (col.DataType == typeof (object))
- col.DataType = typeof (string);
- // When attribute use="prohibited", then it is regarded as
- // Hidden column.
- if (attr.Use == XmlSchemaUse.Prohibited)
- col.ColumnMapping = MappingType.Hidden;
- else {
- col.ColumnMapping = MappingType.Attribute;
- col.DefaultValue = GetAttributeDefaultValue (attr);
- }
- 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);
- AddColumn (col);
- }
- private void ImportColumnElement (XmlSchemaElement parent, XmlSchemaElement el)
- {
- // FIXME: element nest check
- DataColumn col = new DataColumn ();
- 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);
- else
- FillDataColumnSimpleElement (el, col);
- }
- // common process for element and attribute
- private void ImportColumnMetaInfo (XmlSchemaAnnotated obj, XmlQualifiedName name, DataColumn col)
- {
- if (obj.UnhandledAttributes != null) {
- foreach (XmlAttribute attr in obj.UnhandledAttributes) {
- if (attr.NamespaceURI != XmlConstants.MsdataNamespace)
- continue;
- switch (attr.LocalName) {
- case XmlConstants.Caption:
- col.Caption = attr.Value;
- break;
- case XmlConstants.DataType:
- col.DataType = Type.GetType (attr.Value);
- break;
- case XmlConstants.AutoIncrement:
- col.AutoIncrement = bool.Parse (attr.Value);
- break;
- 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:
- int ordinal = int.Parse (attr.Value);
- break;
- }
- }
- }
- }
- private void FillDataColumnComplexElement (XmlSchemaElement parent, XmlSchemaElement el, DataColumn col)
- {
- if (targetElements.Contains (el))
- return; // do nothing
- 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);
- // If xsd:keyref xsd:key for this table exists, then don't add
- // relation here manually.
- else if (!DataSetDefinesKey (elName)) {
- AddParentKeyColumn (parent, el, col);
- RelationStructure rel = new RelationStructure ();
- rel.ParentTableName = XmlHelper.Decode (parent.QualifiedName.Name);
- rel.ChildTableName = elName;
- 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)
- 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 = 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.ColumnName = name;
- col.ColumnMapping = MappingType.Hidden;
- col.Namespace = parent.QualifiedName.Namespace;
- col.DataType = typeof (int);
- col.AutoIncrement = true;
- col.AllowDBNull = false;
- ImportColumnMetaInfo (el, el.QualifiedName, col);
- AddColumn (col);
- currentTable.PrimaryKey = col;
- }
- private void FillDataColumnRepeatedSimpleElement (XmlSchemaElement parent, XmlSchemaElement el, DataColumn col)
- {
- if (targetElements.Contains (el))
- return; // do nothing
- AddParentKeyColumn (parent, el, col);
- DataColumn pkey = currentTable.PrimaryKey;
- string elName = XmlHelper.Decode (el.QualifiedName.Name);
- string parentName = XmlHelper.Decode (parent.QualifiedName.Name);
- DataTable dt = new DataTable ();
- dt.TableName = elName;
- dt.Namespace = el.QualifiedName.Namespace;
- // reference key column to parent
- DataColumn cc = new DataColumn ();
- cc.ColumnName = parentName + "_Id";
- cc.Namespace = parent.QualifiedName.Namespace;
- cc.ColumnMapping = MappingType.Hidden;
- cc.DataType = typeof (int);
- // repeatable content simple element
- DataColumn cc2 = new DataColumn ();
- cc2.ColumnName = elName + "_Column";
- 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);
- dataset.Tables.Add (dt);
- RelationStructure rel = new RelationStructure ();
- rel.ParentTableName = parentName;
- rel.ChildTableName = dt.TableName;
- rel.ParentColumnName = pkey.ColumnName;
- rel.ChildColumnName = cc.ColumnName;
- rel.IsNested = true;
- rel.CreateConstraint = true;
- relations.Add (rel);
- }
- private void FillDataColumnSimpleElement (XmlSchemaElement el, DataColumn col)
- {
- 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);
- AddColumn (col);
- }
- private void AddColumn (DataColumn col)
- {
- if (col.Ordinal < 0)
- currentTable.NonOrdinalColumns.Add (col);
- else
- currentTable.OrdinalColumns.Add (col, col.Ordinal);
- }
- private void FillFacet (DataColumn col, XmlSchemaSimpleType st)
- {
- if (st == null || st.Content == null)
- return;
- // Handle restriction facets
- XmlSchemaSimpleTypeRestriction restriction = st == null ? null : st.Content as XmlSchemaSimpleTypeRestriction;
- if (restriction == null)
- throw new DataException ("DataSet does not suport 'list' nor 'union' simple type.");
- foreach (XmlSchemaFacet f in restriction.Facets) {
- if (f is XmlSchemaMaxLengthFacet)
- // There is no reason why MaxLength is limited to int, except for the fact that DataColumn.MaxLength property is int.
- col.MaxLength = int.Parse (f.Value);
- }
- }
- private Type ConvertDatatype (XmlSchemaDatatype dt)
- {
- if (dt == null)
- return typeof (string);
- else if (dt.ValueType == typeof (decimal)) {
- // LAMESPEC: MSDN documentation says it is based
- // on ValueType. However, in the System.Xml.Schema
- // context, xs:integer is mapped to Decimal, while
- // in DataSet context it is mapped to Int64.
- if (dt == schemaDecimalType)
- return typeof (decimal);
- else if (dt == schemaIntegerType)
- return typeof (long);
- else
- return typeof (ulong);
- }
- else
- return dt.ValueType;
- }
- // This method cuts out the local name of the last step from XPath.
- // It is nothing more than hack. However, MS looks to do similar.
- private string GetSelectorTarget (string xpath)
- {
- string tableName = xpath;
- int index = tableName.LastIndexOf ('/');
- // '>' is enough. If XPath [0] = '/', it is invalid.
- // Selector can specify only element axes.
- if (index > 0)
- tableName = tableName.Substring (index + 1);
- // Round QName to NSName
- index = tableName.LastIndexOf (':');
- if (index > 0)
- tableName = tableName.Substring (index + 1);
- return XmlHelper.Decode (tableName);
- }
- private void ReserveSelfIdentity (XmlSchemaIdentityConstraint ic)
- {
- string tableName = GetSelectorTarget (ic.Selector.XPath);
- 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;
- bool isAttr = colName.Length > 0 && colName [0] == '@';
- int index = colName.LastIndexOf (':');
- if (index > 0)
- colName = colName.Substring (index + 1);
- else if (isAttr)
- colName = colName.Substring (1);
- colName = XmlHelper.Decode (colName);
- cols [i] = colName;
- isAttrSpec [i] = isAttr;
- i++;
- }
-
- bool isPK = false;
- // find if there is an attribute with the constraint name
- // if not use the XmlSchemaConstraint's name.
- string constraintName = ic.Name;
- if (ic.UnhandledAttributes != null) {
- foreach (XmlAttribute attr in ic.UnhandledAttributes) {
- if (attr.NamespaceURI != XmlConstants.MsdataNamespace)
- continue;
- switch (attr.LocalName) {
- case XmlConstants.ConstraintName:
- constraintName = attr.Value;
- break;
- case XmlConstants.PrimaryKey:
- isPK = bool.Parse(attr.Value);
- break;
- }
- }
- }
- reservedConstraints.Add (ic,
- new ConstraintStructure (tableName, cols,
- isAttrSpec, constraintName, isPK, null, false, false));
- }
- private void ProcessSelfIdentity (ConstraintStructure c)
- {
- // Basic concept came from XmlSchemaMapper.cs
- string tableName = c.TableName;
-
- DataTable dt = dataset.Tables [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
- 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;
- bool isAttr = colName.Length > 0 && colName [0] == '@';
- int index = colName.LastIndexOf (':');
- if (index > 0)
- colName = colName.Substring (index + 1);
- else if (isAttr)
- colName = colName.Substring (1);
- 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;
- }
- string name = c.ReferName;
- // get the unique constraint for the releation
- UniqueConstraint uniq = FindConstraint (name, element);
- // generate the FK.
- ForeignKeyConstraint fkc = new ForeignKeyConstraint(c.ConstraintName, uniq.Columns, cols);
- dt.Constraints.Add (fkc);
- 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.
- // name - the name of the XmlSchemaUnique element
- private UniqueConstraint FindConstraint (string name, XmlSchemaElement element)
- {
- // Copied from XmlSchemaMapper.cs
- // find the element in the constraint collection.
- foreach (XmlSchemaIdentityConstraint c in element.Constraints) {
- if (c is XmlSchemaKeyref)
- continue;
- if (c.Name == name) {
- string tableName = GetSelectorTarget (c.Selector.XPath);
- // find the table in the dataset.
- DataTable dt = dataset.Tables [tableName];
- string constraintName = c.Name;
- // find if there is an attribute with the constraint name
- // if not use the XmlSchemaUnique name.
- if (c.UnhandledAttributes != null)
- foreach (XmlAttribute attr in c.UnhandledAttributes)
- if (attr.LocalName == "ConstraintName" && attr.NamespaceURI == XmlConstants.MsdataNamespace)
- constraintName = attr.Value;
- return (UniqueConstraint) dt.Constraints [constraintName];
- }
- }
- throw new DataException ("Target identity constraint was not found: " + name);
- }
- private void HandleAnnotations (XmlSchemaAnnotation an, bool nested)
- {
- foreach (XmlSchemaObject content in an.Items) {
- XmlSchemaAppInfo ai = content as XmlSchemaAppInfo;
- if (ai != null) {
- foreach (XmlNode n in ai.Markup) {
- XmlElement el = n as XmlElement;
-
- // #325464 debugging
- //Console.WriteLine ("Name: " + el.LocalName + " NS: " + el.NamespaceURI + " Const: " + XmlConstants.MsdataNamespace);
- if (el != null && el.LocalName == "Relationship" && el.NamespaceURI == XmlConstants.MsdataNamespace)
- HandleRelationshipAnnotation (el, nested);
- #if NET_2_0
- if (el != null && el.LocalName == "DataSource" && el.NamespaceURI == XmlConstants.MsdatasourceNamespace)
- HandleDataSourceAnnotation (el, nested);
- #endif
- }
- }
- }
- }
- #if NET_2_0
- private void HandleDataSourceAnnotation (XmlElement el, bool nested)
- {
- // Handle: Connections and Tables
- // For Tables: extract the provider information from connection and use
- // the corresponding providerfactory to create the adapter and et al objects
- // and populate them
-
- // #325464 debugging
- //Console.WriteLine ("In HandleDataSourceAnnotation... ");
- string providerName = null;
- string connString = null;
- DbProviderFactory provider;
- XmlElement e;
-
- foreach (XmlNode n in el.ChildNodes) {
- e = n as XmlElement;
-
- if (e == null)
- continue;
-
- if (e.LocalName == "Connections") {
- providerName = ((XmlElement)e.FirstChild).GetAttribute ("Provider");
- connString = ((XmlElement)e.FirstChild).GetAttribute ("AppSettingsPropertyName");
- continue;
- }
- // #325464 debugging
- //Console.WriteLine ("ProviderName: " + providerName + "Connstr: " + connString);
-
- provider = DbProviderFactories.GetFactory (providerName);
-
- if (e.LocalName == "Tables") {
- foreach (XmlNode node in e.ChildNodes) {
- ProcessTableAdapter (node as XmlElement, provider, connString);
- }
- }
- // #325464 debugging
- //Console.WriteLine (e.LocalName);
- }
- // #325464 debugging
- //Console.WriteLine ("... exit");
- }
-
- private void ProcessTableAdapter (XmlElement el, DbProviderFactory provider, string connStr)
- {
- XmlElement e;
- string datasetTableName = null;
-
- if (el == null)
- return;
-
- // #325464 debugging
- //Console.WriteLine ("in ProcessTableAdapters...");
- currentAdapter = new TableAdapterSchemaInfo (provider);
- currentAdapter.ConnectionString = connStr;
-
- //Console.WriteLine ("Provider: {0}, connection: {1}, adapter: {2}",
- // provider, currentAdapter.Connection, currentAdapter.Adapter);
- currentAdapter.BaseClass = el.GetAttribute ("BaseClass");
- datasetTableName = el.GetAttribute ("Name");
- currentAdapter.Name = el.GetAttribute ("GeneratorDataComponentClassName");
-
- if (currentAdapter.Name == null ||
- currentAdapter.Name == String.Empty)
- currentAdapter.Name = el.GetAttribute ("DataAccessorName");
- //Console.WriteLine ("Name: "+currentAdapter.Name);
- foreach (XmlNode n in el.ChildNodes) {
- e = n as XmlElement;
-
- //Console.WriteLine ("Children of Tables: "+e.LocalName);
- if (e == null)
- continue;
-
- switch (e.LocalName) {
- case "MainSource":
- case "Sources":
- foreach (XmlNode msn in e.ChildNodes)
- ProcessDbSource (msn as XmlElement);
- break;
-
- case "Mappings":
- DataTableMapping tableMapping = new DataTableMapping ();
- tableMapping.SourceTable = "Table";
- tableMapping.DataSetTable = datasetTableName;
-
- foreach (XmlNode mps in e.ChildNodes)
- ProcessColumnMapping (mps as XmlElement, tableMapping);
-
- currentAdapter.Adapter.TableMappings.Add (tableMapping);
- break;
- }
- }
- }
-
- private void ProcessDbSource (XmlElement el)
- {
-
- string cmdType;
- string tmp = null;
- XmlElement e;
-
- if (el == null)
- return;
-
- //Console.WriteLine ("ProcessDbSources: "+el.LocalName);
- tmp = el.GetAttribute ("GenerateShortCommands");
- //Console.WriteLine ("GenerateShortCommands: {0}", tmp);
- if (tmp != null && tmp != String.Empty)
- currentAdapter.ShortCommands = Convert.ToBoolean (tmp);
-
- DbCommandInfo cmdInfo = new DbCommandInfo ();
- tmp = el.GetAttribute ("GenerateMethods");
- if (tmp != null && tmp != String.Empty) {
- DbSourceMethodInfo mthdInfo = null;
-
- switch ((GenerateMethodsType) Enum.Parse (typeof (GenerateMethodsType), tmp)) {
- case GenerateMethodsType.Get:
- mthdInfo = new DbSourceMethodInfo ();
- mthdInfo.Name = el.GetAttribute ("GetMethodName");
- mthdInfo.Modifier = el.GetAttribute ("GetMethodModifier");
- if (mthdInfo.Modifier == String.Empty)
- mthdInfo.Modifier = "Public";
- mthdInfo.ScalarCallRetval = el.GetAttribute ("ScalarCallRetval");
- mthdInfo.QueryType = el.GetAttribute ("QueryType");
- mthdInfo.MethodType = GenerateMethodsType.Get;
- cmdInfo.Methods = new DbSourceMethodInfo [1];
- cmdInfo.Methods[0] = mthdInfo;
- break;
-
- case GenerateMethodsType.Fill:
- mthdInfo = new DbSourceMethodInfo ();
- mthdInfo.Name = el.GetAttribute ("FillMethodName");
- mthdInfo.Modifier = el.GetAttribute ("FillMethodModifier");
- if (mthdInfo.Modifier == String.Empty)
- mthdInfo.Modifier = "Public";
- mthdInfo.ScalarCallRetval = null;
- mthdInfo.QueryType = null;
- mthdInfo.MethodType = GenerateMethodsType.Fill;
- cmdInfo.Methods = new DbSourceMethodInfo [1];
- cmdInfo.Methods[0] = mthdInfo;
- break;
-
- case GenerateMethodsType.Both:
- mthdInfo = new DbSourceMethodInfo ();
- // Get
- mthdInfo.Name = el.GetAttribute ("GetMethodName");
- mthdInfo.Modifier = el.GetAttribute ("GetMethodModifier");
- if (mthdInfo.Modifier == String.Empty)
- mthdInfo.Modifier = "Public";
- mthdInfo.ScalarCallRetval = el.GetAttribute ("ScalarCallRetval");
- mthdInfo.QueryType = el.GetAttribute ("QueryType");
- mthdInfo.MethodType = GenerateMethodsType.Get;
- cmdInfo.Methods = new DbSourceMethodInfo [2];
- cmdInfo.Methods[0] = mthdInfo;
-
- // Fill
- mthdInfo = new DbSourceMethodInfo ();
- mthdInfo.Name = el.GetAttribute ("FillMethodName");
- mthdInfo.Modifier = el.GetAttribute ("FillMethodModifier");
- if (mthdInfo.Modifier == String.Empty)
- mthdInfo.Modifier = "Public";
- mthdInfo.ScalarCallRetval = null;
- mthdInfo.QueryType = null;
- mthdInfo.MethodType = GenerateMethodsType.Fill;
- cmdInfo.Methods[1] = mthdInfo;
- break;
- }
- } else {
- // no Get or Fill methods - non <MainSource> sources
- DbSourceMethodInfo mthdInfo = new DbSourceMethodInfo ();
- mthdInfo.Name = el.GetAttribute ("Name");
- mthdInfo.Modifier = el.GetAttribute ("Modifier");
- if (mthdInfo.Modifier == String.Empty)
- mthdInfo.Modifier = "Public";
- mthdInfo.ScalarCallRetval = el.GetAttribute ("ScalarCallRetval");
- mthdInfo.QueryType = el.GetAttribute ("QueryType");
- mthdInfo.MethodType = GenerateMethodsType.None;
- // Add MethodInfo to DbCommandInfo
- cmdInfo.Methods = new DbSourceMethodInfo [1];
- cmdInfo.Methods[0] = mthdInfo;
- }
-
- foreach (XmlNode n in el.ChildNodes) {
- e = n as XmlElement;
-
- if (e == null)
- continue;
-
- switch (e.LocalName) {
- case "SelectCommand":
- cmdInfo.Command = ProcessDbCommand (e.FirstChild as XmlElement);
- currentAdapter.Commands.Add (cmdInfo);
- break;
- case "InsertCommand":
- currentAdapter.Adapter.InsertCommand = ProcessDbCommand (e.FirstChild as XmlElement);
- break;
- case "UpdateCommand":
- currentAdapter.Adapter.UpdateCommand = ProcessDbCommand (e.FirstChild as XmlElement);
- break;
- case "DeleteCommand":
- currentAdapter.Adapter.DeleteCommand = ProcessDbCommand (e.FirstChild as XmlElement);
- break;
- }
- }
- }
-
- private DbCommand ProcessDbCommand (XmlElement el)
- {
- XmlElement e;
- //Console.WriteLine (el.LocalName);
- string cmdText = null;
- string cmdType = null;
- ArrayList parameters = null;
-
- if (el == null)
- return null;
-
- cmdType = el.GetAttribute ("CommandType");
- foreach (XmlNode n in el.ChildNodes) {
- e = n as XmlElement;
- if (e != null && e.LocalName == "CommandText")
- cmdText = e.InnerText;
- else if (e != null && e.LocalName == "Parameters" && !e.IsEmpty)
- parameters = ProcessDbParameters (e);
- }
-
- DbCommand cmd = currentAdapter.Provider.CreateCommand ();
- cmd.CommandText = cmdText;
- if (cmdType == "StoredProcedure")
- cmd.CommandType = CommandType.StoredProcedure;
- else
- cmd.CommandType = CommandType.Text;
- if (parameters != null)
- cmd.Parameters.AddRange (parameters.ToArray ());
-
- //Console.WriteLine ("Parameters count: {0}", cmd.Parameters.Count);
- return cmd;
- }
-
- private ArrayList ProcessDbParameters (XmlElement el)
- {
- //Console.WriteLine ("ProcessDbParameters: "+el.LocalName);
- string tmp = null;
- XmlElement e;
- DbParameter param = null;
- ArrayList parameters = new ArrayList ();
-
- if (el == null)
- return parameters;
-
- foreach (XmlNode n in el.ChildNodes) {
- e = n as XmlElement;
-
- if (e == null)
- continue;
- param = currentAdapter.Provider.CreateParameter ();
- tmp = e.GetAttribute ("AllowDbNull");
- if (tmp != null && tmp != String.Empty)
- param.IsNullable = Convert.ToBoolean (tmp);
-
- param.ParameterName = e.GetAttribute ("ParameterName");
- tmp = e.GetAttribute ("ProviderType");
- if (tmp == null || tmp == String.Empty)
- tmp = e.GetAttribute ("DbType");
- param.FrameworkDbType = tmp;
-
- tmp = e.GetAttribute ("Direction");
- param.Direction = (ParameterDirection) Enum.Parse (typeof (ParameterDirection), tmp);
-
- ((IDbDataParameter)param).Precision = Convert.ToByte (e.GetAttribute ("Precision"));
- ((IDbDataParameter)param).Scale = Convert.ToByte (e.GetAttribute ("Scale"));
- param.Size = Convert.ToInt32 (e.GetAttribute ("Size"));
- param.SourceColumn = e.GetAttribute ("SourceColumn");
-
- tmp = e.GetAttribute ("SourceColumnNullMapping");
- if (tmp != null && tmp != String.Empty)
- param.SourceColumnNullMapping = Convert.ToBoolean (tmp);
-
- tmp = e.GetAttribute ("SourceVersion");
- param.SourceVersion = (DataRowVersion) Enum.Parse (typeof (DataRowVersion), tmp);
- parameters.Add (param);
- }
-
- return parameters;
- }
- private void ProcessColumnMapping (XmlElement el, DataTableMapping tableMapping)
- {
- if (el == null)
- return;
-
- tableMapping.ColumnMappings.Add (el.GetAttribute ("SourceColumn"),
- el.GetAttribute ("DataSetColumn"));
- }
-
- #endif
-
- private void HandleRelationshipAnnotation (XmlElement el, bool nested)
- {
- string name = el.GetAttribute ("name");
- string ptn = el.GetAttribute ("parent", XmlConstants.MsdataNamespace);
- string ctn = el.GetAttribute ("child", XmlConstants.MsdataNamespace);
- string pkn = el.GetAttribute ("parentkey", XmlConstants.MsdataNamespace);
- string fkn = el.GetAttribute ("childkey", XmlConstants.MsdataNamespace);
- RelationStructure rel = new RelationStructure ();
- 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;
- rel.CreateConstraint = false; // by default?
- relations.Add (rel);
- }
- private object GetElementDefaultValue (XmlSchemaElement elem)
- {
- // Unlike attribute, element cannot have a default value.
- if (elem.RefName == XmlQualifiedName.Empty)
- return elem.DefaultValue;
- XmlSchemaElement referenced = schema.Elements [elem.RefName] as XmlSchemaElement;
- if (referenced == null) // considering missing sub components
- return null;
- return referenced.DefaultValue;
- }
- private object GetAttributeDefaultValue (XmlSchemaAttribute attr)
- {
- #if BUGGY_MS_COMPATIBLE
- if (attr == null)
- return null;
- else if (attr.RefName != XmlQualifiedName.Empty) {
- XmlSchemaAttribute referenced = schema.Attributes [attr.RefName] as XmlSchemaAttribute;
- if (referenced != null)
- return referenced.DefaultValue;
- else
- return null;
- }
- if (attr.DefaultValue != null)
- return attr.DefaultValue;
- return attr.FixedValue;
- #else
- if (attr.DefaultValue != null)
- return attr.DefaultValue;
- else if (attr.FixedValue != null)
- return attr.FixedValue;
- else if (attr.RefName == XmlQualifiedName.Empty)
- return null;
- XmlSchemaAttribute referenced = schema.Attributes [attr.RefName] as XmlSchemaAttribute;
- if (referenced == null) // considering missing sub components
- return null;
- if (referenced.DefaultValue != null)
- return referenced.DefaultValue;
- return referenced.FixedValue;
- #endif
- }
- }
- }
|