//****************************************************************************************************** // Schema.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 06/28/2010 - J. Ritchie Carroll // Generated original version of source code. // 08/15/2008 - Mihir Brahmbhatt // Converted to C# extensions. // 09/27/2010 - Mihir Brahmbhatt // Edited code comments. // 12/07/2010 - Mihir Brahmbhatt // Changed SqlEncoded method to check proper numeric conversion value // 12/20/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.OleDb; using System.Globalization; using System.IO; using System.Text; using GSF; using GSF.Data; using GSF.IO; using SerializationFormat = GSF.SerializationFormat; namespace DataMigrationUtility { // James Ritchie Carroll - 2003 #region [ Enumerations ] /// /// Specifies the type of object in database /// [Flags] [Serializable] public enum TableType { /// /// Database object is DataTable /// Table = 1, /// /// Database object is View /// View = 2, /// /// Database object is System Defined Table /// SystemTable = 4, /// /// Database object is System Defined View /// SystemView = 8, /// /// Database object is Alias /// Alias = 16, /// /// Database object is Synonym /// Synonym = 32, /// /// Database object is Global Temp /// GlobalTemp = 64, /// /// Database object is local Temp /// LocalTemp = 128, /// /// Database object is Link /// Link = 256, /// /// Database object is not defined /// Undetermined = 512 } /// /// Specified the type of referential action on database object/Tables /// [Serializable] public enum ReferentialAction { /// /// Action Type is cascade /// Cascade, /// /// Action Type is to set null /// SetNull, /// /// Action Type is to set default /// SetDefault, /// /// No Action /// NoAction } #endregion /// /// Represents a database field. /// [Serializable] public class Field : IComparable { #region [ Members ] //Fields private readonly Fields m_parent; private readonly string m_name; private readonly OleDbType m_dataType; private int m_ordinal; private bool m_allowsNulls; private bool m_autoIncrement; private int m_autoIncrementSeed; private int m_autoIncrementStep; private bool m_hasDefault; private object m_defaultValue; private int m_maxLength; private int m_numericPrecision; private int m_numericScale; private int m_dateTimePrecision; private bool m_readOnly; private bool m_unique; private string m_description; private Hashtable m_autoIncrementTranslations; private object m_value; private bool m_isPrimaryKey; private int m_primaryKeyOrdinal; private string m_primaryKeyName; private ForeignKeyFields m_foreignKeys; private Field m_referencedBy; #endregion #region [ Constructors ] internal Field(Fields Parent, string Name, OleDbType Type) { // We only allow internal creation of this object m_parent = Parent; m_name = Name; m_dataType = Type; ForeignKeys = new ForeignKeyFields(this); } #endregion #region [ Properties ] /// /// Get Field Name /// public string Name { get { return m_name; } } /// /// Get SQL escaped name of /// public string SQLEscapedName { get { return m_parent.Parent.Parent.Parent.SQLEscapeName(m_name); } } /// /// Get Type /// public OleDbType Type { get { return m_dataType; } } /// /// Get or set file ordinal /// public int Ordinal { get { return m_ordinal; } internal set { m_ordinal = value; } } /// /// Get or set Allow Null flag /// public bool AllowsNulls { get { return m_allowsNulls; } internal set { m_allowsNulls = value; } } /// /// Get or set Auto increment flag /// public bool AutoIncrement { get { return m_autoIncrement; } internal set { m_autoIncrement = value; } } /// /// Get or set Auto increment seed /// public int AutoIncrementSeed { get { return m_autoIncrementSeed; } internal set { m_autoIncrementSeed = value; } } /// /// Get or set Auto increment step /// public int AutoIncrementStep { get { return m_autoIncrementStep; } internal set { m_autoIncrementStep = value; } } /// /// Get or set has default value flag /// public bool HasDefault { get { return m_hasDefault; } internal set { m_hasDefault = value; } } /// /// Get or set default value /// public object DefaultValue { get { return m_defaultValue; } internal set { m_defaultValue = value; } } /// /// Get or set maximum length of field /// public int MaxLength { get { return m_maxLength; } internal set { m_maxLength = value; } } /// /// Get or set numeric precision /// public int NumericPrecision { get { return m_numericPrecision; } internal set { m_numericPrecision = value; } } /// /// Get or set Numeric scale /// public int NumericScale { get { return m_numericScale; } internal set { m_numericScale = value; } } /// /// Get or set date time precision /// public int DateTimePrecision { get { return m_dateTimePrecision; } internal set { m_dateTimePrecision = value; } } /// /// Get or set read-only flag /// public bool ReadOnly { get { return m_readOnly; } internal set { m_readOnly = value; } } /// /// Get or set for unique /// public bool Unique { get { return m_unique; } internal set { m_unique = value; } } /// /// Get or set description /// public string Description { get { return m_description; } internal set { m_description = value; } } /// /// Get or set auto increment translation /// internal Hashtable AutoIncrementTranslations { get { return m_autoIncrementTranslations; } set { m_autoIncrementTranslations = value; } } /// /// Get or set value of /// public object Value { get { return m_value; } set { m_value = value; } } /// /// Get or set flag to check is primary key or not /// public bool IsPrimaryKey { get { return m_isPrimaryKey; } set { m_isPrimaryKey = value; } } /// /// Get or set ordinal for Primary key field /// public int PrimaryKeyOrdinal { get { return m_primaryKeyOrdinal; } set { m_primaryKeyOrdinal = value; } } /// /// Get or set primary key name /// public string PrimaryKeyName { get { return m_primaryKeyName; } set { m_primaryKeyName = value; } } /// /// Get or set list of /// public ForeignKeyFields ForeignKeys { get { return m_foreignKeys; } set { m_foreignKeys = value; } } /// /// Get or set - check is reference by /// public Field ReferencedBy { get { return m_referencedBy; } internal set { m_referencedBy = value; } } /// /// Get or set foreign key flag. if is then true else false /// public bool IsForeignKey { get { return ((object)m_referencedBy != null); } } /// /// Get or set parent /// public Fields Parent { get { return m_parent; } } /// /// Get or set 's parent /// public Table Table { get { return m_parent.Parent; } } #endregion #region [ Methods ] /// /// Compare ordinal to current field /// /// Check type , if it is type of then compare to of else throw /// public int CompareTo(object obj) { // Fields are sorted in ordinal position order if (obj is Field) return m_ordinal.CompareTo(((Field)obj).m_ordinal); throw new ArgumentException("Field can only be compared to other Fields"); } /// /// Change value to encoded string. It will check and value before convert to compatible value /// public string SQLEncodedValue { get { string encodedValue = ""; if (!Convert.IsDBNull(m_value)) { try { // Attempt to get string based source field value encodedValue = m_value.ToString().Trim(); // Format field value based on field's data type switch (m_dataType) { case OleDbType.BigInt: case OleDbType.Integer: case OleDbType.SmallInt: case OleDbType.TinyInt: case OleDbType.UnsignedBigInt: case OleDbType.UnsignedInt: case OleDbType.UnsignedSmallInt: case OleDbType.UnsignedTinyInt: case OleDbType.Error: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0"; } } else { Int64 tempValue; if (Int64.TryParse(m_value.ToString(), out tempValue)) //(Information.IsNumeric(Value)) { encodedValue = Convert.ToInt64(Value).ToString().Trim(); } else { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0"; } } } break; case OleDbType.Single: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.0"; } } else { Single tempValue; if (Single.TryParse(m_value.ToString(), out tempValue)) //if (Information.IsNumeric(Value)) { encodedValue = Convert.ToSingle(Value).ToString().Trim(); } else { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.0"; } } } break; case OleDbType.Double: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.0"; } } else { Double tempValue; if (Double.TryParse(m_value.ToString(), out tempValue)) //if (Information.IsNumeric(Value)) { encodedValue = Convert.ToDouble(Value).ToString().Trim(); } else { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.0"; } } } break; case OleDbType.Currency: case OleDbType.Decimal: case OleDbType.Numeric: case OleDbType.VarNumeric: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.00"; } } else { Decimal tempValue; if (Decimal.TryParse(m_value.ToString(), out tempValue)) //if (Information.IsNumeric(Value)) { encodedValue = Convert.ToDecimal(Value).ToString().Trim(); } else { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0.00"; } } } break; case OleDbType.Boolean: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0"; } } else { long tempValue; if (long.TryParse(m_value.ToString(), out tempValue)) //if (Information.IsNumeric(strValue)) { if (tempValue == 0) { encodedValue = "0"; } else { encodedValue = "1"; } } else { switch (char.ToUpper(encodedValue.Trim()[0])) { case 'Y': case 'T': encodedValue = "1"; break; case 'N': case 'F': encodedValue = "0"; break; default: if (m_parent.Parent.Parent.Parent.AllowNumericNulls) { encodedValue = "NULL"; } else { encodedValue = "0"; } break; } } } break; case OleDbType.Char: case OleDbType.WChar: case OleDbType.VarChar: case OleDbType.VarWChar: case OleDbType.LongVarChar: case OleDbType.LongVarWChar: case OleDbType.BSTR: if (encodedValue.Length == 0) { if (m_parent.Parent.Parent.Parent.AllowTextNulls) { encodedValue = "NULL"; } else { encodedValue = "''"; } } else { encodedValue = "'" + encodedValue.SQLEncode(m_parent.Parent.Parent.Parent.DataSourceType) + "'"; } break; case OleDbType.DBTimeStamp: case OleDbType.DBDate: case OleDbType.Date: if (encodedValue.Length > 0) { DateTime tempDateTimeValue; if (DateTime.TryParse(m_value.ToString(), out tempDateTimeValue)) //if (Information.IsDate(strValue)) { switch (m_parent.Parent.Parent.Parent.DataSourceType) { case DatabaseType.Access: encodedValue = "#" + tempDateTimeValue.ToString("MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture) + "#"; break; case DatabaseType.Oracle: encodedValue = "to_date('" + tempDateTimeValue.ToString("dd-MMM-yyyy HH:mm:ss") + "', 'DD-MON-YYYY HH24:MI:SS')"; break; default: encodedValue = "'" + tempDateTimeValue.ToString("yyyy-MM-dd HH:mm:ss") + "'"; break; } } else { encodedValue = "NULL"; } } else { encodedValue = "NULL"; } break; case OleDbType.DBTime: if (encodedValue.Length > 0) { DateTime tempDateTimeValue; if (DateTime.TryParse(m_value.ToString(), out tempDateTimeValue)) //if (Information.IsDate(strValue)) { encodedValue = "'" + tempDateTimeValue.ToString("HH:mm:ss") + "'"; // Strings.Format((DateTime)strValue, "HH:mm:ss") + "'"; } else { encodedValue = "NULL"; } } else { encodedValue = "NULL"; } break; case OleDbType.Filetime: if (encodedValue.Length > 0) { encodedValue = "'" + encodedValue + "'"; } else { encodedValue = "NULL"; } break; case OleDbType.Guid: if (encodedValue.Length == 0) { encodedValue = (new Guid()).ToString().ToLower(); } if (m_parent.Parent.Parent.Parent.DataSourceType == DatabaseType.Access) { encodedValue = "{" + encodedValue.ToLower() + "}"; } else { encodedValue = "'" + encodedValue.ToLower() + "'"; } break; } } catch //(Exception ex) { // We'll default to NULL if we failed to evaluate field data encodedValue = "NULL"; } } if (encodedValue.Length == 0) encodedValue = "NULL"; return encodedValue; } } /// /// Gets the native value for the field (SQL Encoded). /// public string NonNullNativeValue { get { string encodedValue = ""; // Format field value based on field's data type switch (m_dataType) { case OleDbType.BigInt: case OleDbType.Integer: case OleDbType.SmallInt: case OleDbType.TinyInt: case OleDbType.UnsignedBigInt: case OleDbType.UnsignedInt: case OleDbType.UnsignedSmallInt: case OleDbType.UnsignedTinyInt: case OleDbType.Error: case OleDbType.Boolean: encodedValue = "0"; break; case OleDbType.Single: case OleDbType.Double: case OleDbType.Currency: case OleDbType.Decimal: case OleDbType.Numeric: case OleDbType.VarNumeric: encodedValue = "0.00"; break; case OleDbType.Char: case OleDbType.WChar: case OleDbType.VarChar: case OleDbType.VarWChar: case OleDbType.LongVarChar: case OleDbType.LongVarWChar: case OleDbType.BSTR: case OleDbType.Filetime: encodedValue = "''"; break; case OleDbType.DBTimeStamp: case OleDbType.DBDate: case OleDbType.Date: switch (m_parent.Parent.Parent.Parent.DataSourceType) { case DatabaseType.Access: encodedValue = "#" + DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture) + "#"; break; case DatabaseType.Oracle: encodedValue = "to_date('" + DateTime.UtcNow.ToString("dd-MMM-yyyy HH:mm:ss") + "', 'DD-MON-YYYY HH24:MI:SS')"; break; default: encodedValue = "'" + DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + "'"; break; } break; case OleDbType.DBTime: encodedValue = "'" + DateTime.UtcNow.ToString("HH:mm:ss") + "'"; break; case OleDbType.Guid: encodedValue = (new Guid()).ToString().ToLower(); if (m_parent.Parent.Parent.Parent.DataSourceType == DatabaseType.Access) encodedValue = "{" + encodedValue + "}"; else encodedValue = "'" + encodedValue + "'"; break; } return encodedValue; } } /// /// Get information about referential action /// /// check and return to appropriate . /// static internal ReferentialAction GetReferentialAction(string action) { switch (action.Trim().ToUpper()) { case "CASCADE": return ReferentialAction.Cascade; case "SET NULL": return ReferentialAction.SetNull; case "SET DEFAULT": return ReferentialAction.SetDefault; case "NO ACTION": return ReferentialAction.NoAction; default: return ReferentialAction.NoAction; } } #endregion } /// /// Represents a database foreign key field. /// [Serializable] public class ForeignKeyField { #region [ Members ] private readonly ForeignKeyFields m_Parent; private Field m_primaryKey; private Field m_foreignKey; private int m_ordinal; private string m_keyName; private ReferentialAction m_updateRule = ReferentialAction.NoAction; private ReferentialAction m_deleteRule = ReferentialAction.NoAction; #endregion #region [ Constructors ] internal ForeignKeyField(ForeignKeyFields Parent) { // We only allow internal creation of this object m_Parent = Parent; } #endregion #region [ Properties ] /// /// Get foreign key parent information /// public ForeignKeyFields Parent { get { return m_Parent; } } /// /// Get or set Primary key field /// public Field PrimaryKey { get { return m_primaryKey; } set { m_primaryKey = value; } } /// /// Get or set Foreign key field /// public Field ForeignKey { get { return m_foreignKey; } set { m_foreignKey = value; } } /// /// Get or set ordinal of /// public int Ordinal { get { return m_ordinal; } set { m_ordinal = value; } } /// /// Get or set name of key /// public string KeyName { get { return m_keyName; } set { m_keyName = value; } } /// /// Get or set update rule for for /// public ReferentialAction UpdateRule { get { return m_updateRule; } set { m_updateRule = value; } } /// /// Get or set delete rule for for /// public ReferentialAction DeleteRule { get { return m_deleteRule; } set { m_deleteRule = value; } } #endregion } /// /// Represents a collection of values. /// [Serializable] public class ForeignKeyFields : IEnumerable { #region [ Members ] private readonly Field m_parent; private readonly Dictionary m_fields; // Used for field name lookups private readonly List m_fieldList; // Used for field index lookups #endregion #region [ Constructors ] internal ForeignKeyFields(Field Parent) { // We only allow internal creation of this object m_parent = Parent; m_fields = new Dictionary(StringComparer.OrdinalIgnoreCase); m_fieldList = new List(); } #endregion #region [ Properties ] /// /// Get or set field parent information /// public Field Parent { get { return m_parent; } //internal set //{ // m_Parent = value; //} } /// /// Get of Set Fields names to lookups /// internal Dictionary FieldDictionary { get { return m_fields; } } /// /// Get or set field indexes to lookups /// internal List FieldsList { get { return m_fieldList; } } /// /// Get the current index of foreign key field information /// /// /// public ForeignKeyField this[int index] { get { if (index < 0 || index >= m_fieldList.Count) return null; return m_fieldList[index]; } } /// /// Get the current information by name /// /// /// public ForeignKeyField this[string name] { get { ForeignKeyField lookup; m_fields.TryGetValue(name, out lookup); return lookup; } } /// /// Get count of list /// public int Count { get { return m_fieldList.Count; } } #endregion #region [ Methods ] /// /// Get of field lists /// /// public IEnumerator GetEnumerator() { return m_fieldList.GetEnumerator(); } /// /// Add a to list object /// /// is type of internal void Add(ForeignKeyField newField) { m_fieldList.Add(newField); m_fields.Add((newField.KeyName.Length > 0 ? newField.KeyName : "FK" + m_fieldList.Count), newField); } /// /// Get comma separated of /// /// public string GetList() { StringBuilder fieldList = new StringBuilder(); foreach (ForeignKeyField field in m_fieldList) { if (fieldList.Length > 0) fieldList.Append(','); fieldList.Append('['); fieldList.Append(field.ForeignKey.Name); fieldList.Append(']'); } return fieldList.ToString(); } #endregion } /// /// Represents a collection of values. /// [Serializable] public class Fields : IEnumerable { #region [ Members ] private readonly Table m_parent; // Used for field name lookups private readonly Dictionary m_fields; // Used for field index lookups private readonly List m_fieldList; #endregion #region [ Constructors ] internal Fields(Table Parent) { // We only allow internal creation of this object m_parent = Parent; m_fields = new Dictionary(StringComparer.OrdinalIgnoreCase); m_fieldList = new List(); } #endregion #region [ Properties ] /// /// Get 's parent . /// public Table Parent { get { return m_parent; } } /// /// Get or set to fields lookup /// internal Dictionary FieldDictionary { get { return m_fields; } } /// /// Get or set Fields index lookup /// internal List FieldList { get { return m_fieldList; } } /// /// Indexer property of Field /// /// /// public Field this[int index] { get { if (index < 0 || index >= m_fieldList.Count) return null; return m_fieldList[index]; } } /// /// Indexer property of Field by Name /// /// /// public Field this[string name] { get { Field lookup; m_fields.TryGetValue(name, out lookup); return lookup; } } /// /// Get count of collection of /// public int Count { get { return m_fieldList.Count; } } #endregion #region [ Methods ] /// /// Add new to this collection. /// /// Field to add. internal void Add(Field newField) { m_fields.Add(newField.Name, newField); m_fieldList.Add(newField); } /// /// Removes from the collection. /// /// Field to remove. internal void Remove(Field field) { m_fields.Remove(field.Name); m_fieldList.Remove(field); } /// /// Get type of list. /// /// public IEnumerator GetEnumerator() { return m_fieldList.GetEnumerator(); } /// /// Get comma separated list of /// /// /// /// public string GetList(bool returnAutoInc = true, Func sqlEscapeFunction = null) { if ((object)sqlEscapeFunction == null) sqlEscapeFunction = m_parent.Parent.Parent.SQLEscapeName; StringBuilder fieldList = new StringBuilder(); foreach (Field field in m_fieldList) { if (!field.AutoIncrement || returnAutoInc) { if (fieldList.Length > 0) fieldList.Append(", "); fieldList.Append(sqlEscapeFunction(field.Name)); } } return fieldList.ToString(); } #endregion } /// /// Get data table information for data processing /// [Serializable] public class Table : IComparable, IComparable { #region [ Members ] private readonly Tables m_parent; private readonly string m_catalog; private readonly string m_schema; private readonly string m_name; private readonly TableType m_tableType; private readonly string m_description; private int m_rows; private Fields m_fields; // This is the name that will be used during table mapping when using a data handler private string m_mapName; // This flag allows users to override whether or not table will be processed in a data operation private bool m_process; // This is the user-overridable I/O process priority for a table private int m_priority; // User definable SQL used to retrieve last auto-inc value from identity column private string m_identitySQL = "SELECT @@IDENTITY"; #endregion #region [ Consturctors ] internal Table(Tables parent, string catalog, string schema, string name, string type, string description, int rows) { // We only allow internal creation of this object m_parent = parent; m_fields = new Fields(this); m_catalog = catalog; m_schema = schema; m_name = name; m_mapName = name; m_description = description; switch (type.Trim().ToUpper()) { case "TABLE": m_tableType = TableType.Table; break; case "VIEW": m_tableType = TableType.View; break; case "SYSTEM TABLE": m_tableType = TableType.SystemTable; break; case "SYSTEM VIEW": m_tableType = TableType.SystemView; break; case "ALIAS": m_tableType = TableType.Alias; break; case "SYNONYM": m_tableType = TableType.Synonym; break; case "GLOBAL TEMPORARY": m_tableType = TableType.GlobalTemp; break; case "LOCAL TEMPORARY": m_tableType = TableType.LocalTemp; break; case "LINK": m_tableType = TableType.Link; break; default: m_tableType = TableType.Undetermined; break; } if (rows == 0) CalculateRowCount(); else m_rows = rows; ReevalulateIdentitySQL(); } #endregion #region [ Properties ] /// /// Get or set list of for /// public Fields Fields { get { return m_fields; } set { m_fields = value; } } /// /// Get or set name of /// public string MapName { get { return m_mapName; } set { m_mapName = value; } } /// /// Get or set process flag /// public bool Process { get { return m_process; } set { m_process = value; } } /// /// Get or set priority /// public int Priority { get { return m_priority; } set { m_priority = value; } } /// /// Get or set identity SQL for /// public string IdentitySQL { get { return m_identitySQL; } set { m_identitySQL = value; } } /// /// Get name of /// public string Name { get { return m_name; } } /// /// Get SQL escaped name of /// public string SQLEscapedName { get { return m_parent.Parent.SQLEscapeName(m_name); } } /// /// Get or set full name of /// public string FullName { get { Schema schema = m_parent.Parent; string strFullName = ""; if (!string.IsNullOrWhiteSpace(m_catalog)) strFullName += schema.SQLEscapeName(m_catalog) + "."; if (!string.IsNullOrWhiteSpace(m_schema)) strFullName += schema.SQLEscapeName(m_schema) + "."; strFullName += schema.SQLEscapeName(m_name); return strFullName; } } /// /// Get or set catalog information for /// public string Catalog { get { return m_catalog; } } /// /// Get or set schema name /// public string Schema { get { return m_schema; } } /// /// Get /// public TableType Type { get { return m_tableType; } } /// /// Get or set description /// public string Description { get { return m_description; } } /// /// Get row count in /// public int RowCount { get { return m_rows; } } /// /// Get parent information /// public Tables Parent { get { return m_parent; } } /// /// Get of object /// public IDbConnection Connection { get { return m_parent.Parent.Connection; } } /// /// Check for object is view /// public bool IsView { get { return (m_tableType == TableType.View || m_tableType == TableType.SystemView); } } /// /// Check for system tables and system views /// public bool IsSystem { get { return (m_tableType == TableType.SystemTable || m_tableType == TableType.SystemView); } } /// /// Get flag for for temp /// public bool IsTemporary { get { return (m_tableType == TableType.GlobalTemp || m_tableType == TableType.LocalTemp); } } /// /// Get flag for alias or link /// public bool IsLinked { get { return (m_tableType == TableType.Alias || m_tableType == TableType.Link); } } /// /// Get count for primary key /// public int PrimaryKeyFieldCount { get { int count = 0; foreach (Field field in m_fields) { if (field.IsPrimaryKey) count += 1; } return count; } } /// /// Get flag that determines if the table has any foreign keys. /// public bool ReferencedByForeignKeys { get { foreach (Field field in m_fields) { if (field.IsPrimaryKey && field.ForeignKeys.Count > 0) return true; } return false; } } /// /// Get flag of any foreign key /// public bool IsForeignKeyTable { get { foreach (Field field in m_fields) { if (field.IsForeignKey) return true; } return false; } } /// /// Gets flag that determines if the has an auto-increment field. /// public bool HasAutoIncField { get { return (object)AutoIncField != null; } } /// /// Gets auto-increment field for the , if any. /// public Field AutoIncField { get { foreach (Field field in m_fields) { if (field.AutoIncrement) return field; } return null; } } #endregion #region [ Methods ] /// /// Get schema information flag based on /// /// public bool UsesDefaultSchema() { if (Parent.Parent.DataSourceType == DatabaseType.SQLServer) return (string.Compare(m_schema, "dbo", StringComparison.OrdinalIgnoreCase) == 0); return (Schema.Length == 0); } /// /// Gets display name for table. /// public override string ToString() { return MapName; } /// /// Compare type of with object /// /// /// public int CompareTo(object obj) { // Tables are sorted in priority order if (obj is Table) return CompareTo(obj as Table); throw new ArgumentException("Table can only be compared to other Tables"); } /// /// Compare Table with other object /// /// /// public int CompareTo(Table other) { return m_priority.CompareTo(other.Priority); } /// /// Check for reference flag, whether table has reference in another table /// /// /// /// internal bool IsReferencedBy(Table otherTable, List
tableStack) { Table table; bool tableIsInStack; if ((object)tableStack == null) tableStack = new List
(); tableStack.Add(this); foreach (Field field in m_fields) { foreach (ForeignKeyField foreignKey in field.ForeignKeys) { // We don't want to circle back on ourselves table = foreignKey.ForeignKey.Table; tableIsInStack = tableStack.Exists(tbl => string.Compare(tbl.Name, table.Name, StringComparison.OrdinalIgnoreCase) == 0); if (tableIsInStack) { if (string.Compare(table.Name, otherTable.Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } else { if (table.IsReferencedBy(otherTable, tableStack)) return true; if (string.Compare(table.Name, otherTable.Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } } } return false; } /// /// Check for table reference /// /// /// public bool IsReferencedBy(Table otherTable) { return IsReferencedBy(otherTable, null); } public bool IsReferencedVia(Table otherTable) { Table table; foreach (Field field in otherTable.Fields) { foreach (ForeignKeyField foreignKey in field.ForeignKeys) { table = foreignKey.ForeignKey.Table; // Not a direct relation, but children are related if (string.Compare(m_name, table.Name, StringComparison.OrdinalIgnoreCase) != 0 && IsReferencedBy(table)) return true; } } return false; } /// /// check for primary key field in /// /// /// /// /// public bool DefinePrimaryKey(string fieldName, int primaryKeyOrdinal = -1, string primaryKeyName = "") { Field lookupField; lookupField = m_fields[fieldName]; if ((object)lookupField != null) { lookupField.IsPrimaryKey = true; lookupField.PrimaryKeyOrdinal = (primaryKeyOrdinal == -1 ? PrimaryKeyFieldCount + 1 : primaryKeyOrdinal); lookupField.PrimaryKeyName = primaryKeyName; return true; } return false; } /// /// Check for /// /// /// /// /// /// /// /// /// public bool DefineForeignKey(string primaryKeyFieldName, string foreignKeyTableName, string foreignKeyFieldName, int foreignKeyOrdinal = -1, string foreignKeyName = "", ReferentialAction foreignKeyUpdateRule = ReferentialAction.NoAction, ReferentialAction foreignKeyDeleteRule = ReferentialAction.NoAction) { Field localPrimaryKeyField; Table remoteForeignKeyTable; Field remoteForeignKeyField; localPrimaryKeyField = m_fields[primaryKeyFieldName]; if ((object)localPrimaryKeyField != null) { remoteForeignKeyTable = m_parent[foreignKeyTableName]; if ((object)remoteForeignKeyTable != null) { remoteForeignKeyField = remoteForeignKeyTable.Fields[foreignKeyFieldName]; if ((object)remoteForeignKeyField != null) { ForeignKeyField localForeignKeyField = new ForeignKeyField(localPrimaryKeyField.ForeignKeys); localForeignKeyField.PrimaryKey = localPrimaryKeyField; localForeignKeyField.ForeignKey = remoteForeignKeyField; localForeignKeyField.ForeignKey.ReferencedBy = localForeignKeyField.PrimaryKey; localForeignKeyField.Ordinal = (foreignKeyOrdinal == -1 ? localPrimaryKeyField.ForeignKeys.Count + 1 : foreignKeyOrdinal); localForeignKeyField.KeyName = foreignKeyName; localForeignKeyField.UpdateRule = foreignKeyUpdateRule; localForeignKeyField.DeleteRule = foreignKeyDeleteRule; localPrimaryKeyField.ForeignKeys.Add(localForeignKeyField); return true; } } } return false; } public void ReevalulateIdentitySQL() { switch (m_parent.Parent.DataSourceType) { case DatabaseType.SQLServer: m_identitySQL = "SELECT IDENT_CURRENT('" + Name + "')"; break; case DatabaseType.Oracle: m_identitySQL = "SELECT SEQ_" + Name + ".CURRVAL from dual"; break; case DatabaseType.SQLite: m_identitySQL = "SELECT last_insert_rowid()"; break; case DatabaseType.PostgreSQL: if ((object)AutoIncField != null) m_identitySQL = "SELECT currval(pg_get_serial_sequence('" + Name.ToLower() + "', '" + AutoIncField.Name.ToLower() + "'))"; else m_identitySQL = "SELECT lastval()"; break; default: m_identitySQL = "SELECT @@IDENTITY"; break; } } public void CalculateRowCount() { if (m_tableType == TableType.Table) { try { IDbCommand command = m_parent.Parent.Connection.CreateCommand(); command.CommandText = "SELECT COUNT(*) FROM " + SQLEscapedName; command.CommandType = CommandType.Text; m_rows = Convert.ToInt32(command.ExecuteScalar()); } catch { m_rows = 0; } } } #endregion } /// /// List of collection /// [Serializable] public class Tables : IEnumerable { #region [ Memebers ] //Fields private Schema m_parent; // Used for table name lookups private readonly Dictionary m_tables; // Used for table index lookups private readonly List
m_tableList; #endregion #region [ Constructor ] internal Tables(Schema Parent) { // We only allow internal creation of this object m_parent = Parent; m_tables = new Dictionary(StringComparer.OrdinalIgnoreCase); m_tableList = new List
(); } #endregion #region [ Properties ] internal Dictionary TableDictionary { get { return m_tables; } } internal List
TableList { get { return m_tableList; } } public int Count { get { return m_tableList.Count; } } public Schema Parent { get { return m_parent; } internal set { m_parent = value; foreach (Table table in m_tableList) { table.ReevalulateIdentitySQL(); } } } #endregion #region [ Methods ] internal void Add(Table table) { m_tables.Add(table.Name, table); m_tableList.Add(table); } internal void Remove(Table table) { m_tables.Remove(table.Name); m_tableList.Remove(table); } public Table this[int index] { get { if (index < 0 || index >= m_tableList.Count) return null; return m_tableList[index]; } } public Table this[string name] { get { Table lookup; m_tables.TryGetValue(name, out lookup); return lookup; } } public Table FindByMapName(string mapName) { foreach (Table table in m_tableList) { if (string.Compare(table.MapName, mapName, StringComparison.OrdinalIgnoreCase) == 0) return table; } return null; } public IEnumerator GetEnumerator() { return m_tableList.GetEnumerator(); } public string GetList() { StringBuilder fieldList = new StringBuilder(); foreach (Table tbl in m_tableList) { if (fieldList.Length > 0) fieldList.Append(','); fieldList.Append(tbl.SQLEscapedName); } return fieldList.ToString(); } #endregion #region [ Inner Class ] /// /// Check for referential order of /// public class ReferentialOrderComparer : IComparer
{ #region [ Properties ] /// /// Default property of object /// public readonly static ReferentialOrderComparer Default = new ReferentialOrderComparer(); #endregion #region [ Methods ] /// /// Allows tables to be sorted in proper referential integrity process object /// /// First table to compare. /// Second table to compare. /// public int Compare(Table table1, Table table2) { // This function allows tables to be sorted in proper referential integrity process order int result = 0; if (table1 == table2) return 0; if (table1.IsReferencedBy(table2))// || table1.IsReferencedVia(table2)) result = -1; else if (table2.IsReferencedBy(table1))// || table2.IsReferencedVia(table1)) result = 1; // Sort by existence of foreign key fields, if defined if (result == 0) result = ForeignKeyCompare(table1, table2); return result; } /// /// Compare foreign key comparison of tables /// /// /// /// private int ForeignKeyCompare(Table table1, Table table2) { if (table1.IsForeignKeyTable && table2.IsForeignKeyTable) return 0; // Both tables have foreign key fields, consider them equal if (!table1.IsForeignKeyTable && !table2.IsForeignKeyTable) return 0; // Neither table has foreign key fields, consider them equal if (table1.IsForeignKeyTable) return 1; // Table1 has foreign key fields and Table2 does not, sort it below return -1; // Table2 has foreign key fields and Table1 does not, sort it below } ///// ///// We compare based on the existence of AutoInc fields as a secondary compare in case user ///// has no defined relational integrity - lastly we just sort by table name ///// ///// ///// ///// //private int AutoIncCompare(Table tbl1, Table tbl2) //{ // return (tbl1.HasAutoIncField == tbl2.HasAutoIncField ? 0 : (tbl1.HasAutoIncField ? -1 : 1)); //} #endregion } #endregion } /// /// Get information about database schema /// [Serializable] public class Schema { #region [ Members ] // Fields private Tables m_tables; public const TableType NoRestriction = TableType.Table | TableType.View | TableType.SystemTable | TableType.SystemView | TableType.Alias | TableType.Synonym | TableType.GlobalTemp | TableType.LocalTemp | TableType.Link | TableType.Undetermined; [NonSerialized] private IDbConnection m_schemaConnection; [NonSerialized] private string m_connectionString; private DatabaseType m_databaseType; private TableType m_restriction; private bool m_immediateClose; private bool m_allowTextNulls; private bool m_allowNumericNulls; #endregion #region [ Constructors ] public Schema() { m_connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\SourceDB.mdb"; m_databaseType = DatabaseType.Other; m_restriction = NoRestriction; m_immediateClose = true; m_allowTextNulls = false; m_allowNumericNulls = false; } public Schema(string connectionString, TableType tableTypeRestriction = NoRestriction, bool immediateClose = true, bool anaylzeNow = true) { m_connectionString = connectionString; m_restriction = tableTypeRestriction; m_immediateClose = immediateClose; m_allowTextNulls = false; m_allowNumericNulls = false; if (anaylzeNow) Analyze(); } #endregion #region [ Properties ] /// /// Get or set - information to process /// public Tables Tables { get { return m_tables; } set { m_tables = value; } } /// /// OLEDB connection string to data source to analyze. /// public string ConnectionString { get { return m_connectionString; } set { m_connectionString = value; } } /// /// Set this value to restrict the types of tables returned in your schema. Table types can be OR'd together to create this table type restriction. /// public TableType TableTypeRestriction { get { return m_restriction; } set { m_restriction = value; } } /// /// Set this value to False to keep the schema connection used during analysis open after analysis is complete. /// public bool ImmediateClose { get { return m_immediateClose; } set { m_immediateClose = value; } } /// /// Type of database specified in connect string. /// public DatabaseType DataSourceType { get { return m_databaseType; } set { m_databaseType = value; } } /// /// Set this value to False to convert all Null values encountered in character fields to empty strings. /// public bool AllowTextNulls { get { return m_allowTextNulls; } set { m_allowTextNulls = value; } } /// /// Set this value to False to convert all Null values encountered in numeric fields to zeros. /// public bool AllowNumericNulls { get { return m_allowNumericNulls; } set { m_allowNumericNulls = value; } } /// /// to open a database connection /// public IDbConnection Connection { get { return m_schemaConnection; } } #endregion #region [ Methods ] /// /// Escapes a field or table name. /// /// Name to escape. /// Escaped . public string SQLEscapeName(string name) { switch (m_databaseType) { case DatabaseType.Access: case DatabaseType.SQLServer: return "[" + name + "]"; case DatabaseType.Oracle: return "\"" + name.ToUpper() + "\""; case DatabaseType.PostgreSQL: return "\"" + name.ToLower() + "\""; } return "\"" + name + "\""; } /// /// Analyze data schema for processing data /// public void Analyze() { DatabaseType databaseType; Schema deserializedSchema; bool isAdoConnection; m_schemaConnection = OpenConnection(m_connectionString, out databaseType, out deserializedSchema, out isAdoConnection); if (isAdoConnection) { if ((object)deserializedSchema == null) throw new InvalidOperationException("Cannot use an ADO style connection with out a serialized schema.\r\nValidate that the \"serializedSchema\" connection string parameter exists and refers to an existing file."); // Reference table collection from deserialized collection m_tables = deserializedSchema.Tables; // Update database type and force re-evaluation of SQL identity statements m_databaseType = databaseType; m_tables.Parent = this; // Set normal ANSI SQL quotes mode for MySQL if (databaseType == DatabaseType.MySQL) m_schemaConnection.ExecuteNonQuery("SET sql_mode='ANSI_QUOTES'"); // Validate table / field existence against open connection as defined in serialized schema List
tablesToRemove = new List
(); foreach (Table table in m_tables) { try { // Make sure table exists m_schemaConnection.ExecuteScalar("SELECT COUNT(*) FROM " + table.SQLEscapedName); List fieldsToRemove = new List(); string testFieldSQL; try { // If table has an auto-inc field, this will typically be indexed and will allow for a faster field check than a count if (table.HasAutoIncField) testFieldSQL = "SELECT {0} FROM " + table.SQLEscapedName + " WHERE " + table.AutoIncField.SQLEscapedName + " < 0"; else testFieldSQL = "SELECT COUNT({0}) FROM " + table.SQLEscapedName; } catch { testFieldSQL = "SELECT COUNT({0}) FROM " + table.SQLEscapedName; } foreach (Field field in table.Fields) { try { // Make sure field exists m_schemaConnection.ExecuteScalar(string.Format(testFieldSQL, field.SQLEscapedName)); } catch { fieldsToRemove.Add(field); } } foreach (Field field in fieldsToRemove) { table.Fields.Remove(field); } } catch { tablesToRemove.Add(table); } } foreach (Table table in tablesToRemove) { m_tables.Remove(table); } // Check to see if user requested to keep connection open, this is just for convience... if (m_immediateClose) Close(); return; } // If connection is OleDB, attempt to directly infer schema AnalyzeOleDbSchema(); } private void AnalyzeOleDbSchema() { DataRow row; Table table; Field field; int x; int y; // See http://technet.microsoft.com/en-us/library/ms131488.aspx for detailed OLEDB schema row set information m_tables = new Tables(this); OleDbConnection oledbSchemaConnection = m_schemaConnection as OleDbConnection; if ((object)oledbSchemaConnection == null) throw new NullReferenceException("Current connection is an ADO style connection, OLE DB connection expected"); // Attach to schema connection state change event oledbSchemaConnection.StateChange += SchemaConnection_StateChange; // Load all tables and views into the schema DataTable schemaTable = oledbSchemaConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables_Info, null); if ((object)schemaTable == null) throw new NullReferenceException("Failed to retrieve OLE DB schema table for OleDbSchemaGuid.Tables_Info"); for (x = 0; x < schemaTable.Rows.Count; x++) { row = schemaTable.Rows[x]; table = new Table(m_tables, Common.NotNull(row["TABLE_CATALOG"]), Common.NotNull(row["TABLE_SCHEMA"]), row["TABLE_NAME"].ToString(), row["TABLE_TYPE"].ToString(), Common.NotNull(row["DESCRIPTION"], ""), 0); if ((table.Type & m_restriction) == m_restriction) { // Both the data adapter and the OleDB schema row sets provide column properties // that the other doesn't - so we use both to get a very complete schema DataSet data = new DataSet(); OleDbDataAdapter adapter = new OleDbDataAdapter(); if (table.Name.IndexOf(' ') == -1 & table.UsesDefaultSchema()) { try { // For standard table names we can use direct table commands for speed adapter.SelectCommand = new OleDbCommand(table.Name, oledbSchemaConnection); adapter.SelectCommand.CommandType = CommandType.TableDirect; adapter.FillSchema(data, SchemaType.Mapped); } catch { // We'll fall back on the standard method (maybe provider doesn't support TableDirect) adapter.SelectCommand = new OleDbCommand("SELECT TOP 1 * FROM " + table.FullName, oledbSchemaConnection); adapter.FillSchema(data, SchemaType.Mapped); } } else { // For schema based databases and non-standard table names we must use a regular select command adapter.SelectCommand = new OleDbCommand("SELECT TOP 1 * FROM " + table.FullName, oledbSchemaConnection); adapter.FillSchema(data, SchemaType.Mapped); } // Load all column data into the schema DataTable currentTable = oledbSchemaConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, table.Name }); if ((object)currentTable != null) { for (y = 0; y < currentTable.Rows.Count; y++) { row = currentTable.Rows[y]; // New field encountered, create new field field = new Field(table.Fields, row["COLUMN_NAME"].ToString(), (OleDbType)row["DATA_TYPE"]); field.HasDefault = Convert.ToBoolean(Common.NotNull(row["COLUMN_HASDEFAULT"], "0")); field.NumericPrecision = Convert.ToInt32(Common.NotNull(row["NUMERIC_PRECISION"], "0")); field.NumericScale = Convert.ToInt32(Common.NotNull(row["NUMERIC_SCALE"], "0")); field.DateTimePrecision = Convert.ToInt32(Common.NotNull(row["DATETIME_PRECISION"], "0")); field.Description = Common.NotNull(row["DESCRIPTION"], ""); // We also use as many properties as we can from data adapter schema field.Ordinal = data.Tables[0].Columns[field.Name].Ordinal; field.AllowsNulls = data.Tables[0].Columns[field.Name].AllowDBNull; field.DefaultValue = data.Tables[0].Columns[field.Name].DefaultValue; field.MaxLength = data.Tables[0].Columns[field.Name].MaxLength; field.AutoIncrement = data.Tables[0].Columns[field.Name].AutoIncrement; field.AutoIncrementSeed = Convert.ToInt32(data.Tables[0].Columns[field.Name].AutoIncrementSeed); field.AutoIncrementStep = Convert.ToInt32(data.Tables[0].Columns[field.Name].AutoIncrementStep); field.ReadOnly = data.Tables[0].Columns[field.Name].ReadOnly; field.Unique = data.Tables[0].Columns[field.Name].Unique; // Add field to table's field collection table.Fields.Add(field); } } // Sort all loaded fields in ordinal order table.Fields.FieldList.Sort(); // Define primary keys try { DataTable primaryKeyTable = oledbSchemaConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Primary_Keys, new object[] { null, null, table.Name }); if ((object)primaryKeyTable != null) { for (y = 0; y <= primaryKeyTable.Rows.Count - 1; y++) { row = primaryKeyTable.Rows[y]; table.DefinePrimaryKey(row["COLUMN_NAME"].ToString(), Convert.ToInt32(Common.NotNull(row["ORDINAL"], "-1")), Common.NotNull(row["PK_NAME"], "")); } } } catch { // It's possible that the data source doesn't provide a primary keys row set } // Add table to schema's table collection m_tables.Add(table); } } // Define foreign keys (must be done after all tables are defined so relations can be properly established) for (int i = 0; i < m_tables.Count; i++) { table = m_tables[i]; try { DataTable foreignKeyTable = oledbSchemaConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Foreign_Keys, new object[] { null, null, table.Name }); if ((object)foreignKeyTable != null) { for (x = 0; x <= foreignKeyTable.Rows.Count - 1; x++) { row = foreignKeyTable.Rows[x]; table.DefineForeignKey(row["PK_COLUMN_NAME"].ToString(), row["FK_TABLE_NAME"].ToString(), row["FK_COLUMN_NAME"].ToString(), Convert.ToInt32(Common.NotNull(row["ORDINAL"], "-1")), Common.NotNull(row["FK_NAME"], ""), Field.GetReferentialAction(Common.NotNull(row["UPDATE_RULE"], "")), Field.GetReferentialAction(Common.NotNull(row["DELETE_RULE"], ""))); } } } catch { // It's possible that the data source doesn't provide a foreign keys row set } } // Using a simple (i.e., stable) sorting algorithm here since not all relationships will // be considered mathematically congruent and the fast .NET sort algorithm depends on // comparisons based on perfect equality (i.e., if A > B and B > C then A > C - this may // not be true in terms of referential integrity) List
sortedList = new List
(m_tables.TableList); Table temp; for (x = 0; x < sortedList.Count; x++) { for (y = 0; y < sortedList.Count; y++) { if (x != y && Tables.ReferentialOrderComparer.Default.Compare(sortedList[x], sortedList[y]) < 0) { temp = sortedList[y]; sortedList[y] = sortedList[x]; sortedList[x] = temp; } } } // Set initial I/O processing priorities for tables based on this order. Processing tables // based on the "Priority" field allows user to have final say in processing order for (x = 0; x < sortedList.Count; x++) { m_tables.TableList.Find(tbl => string.Compare(tbl.Name, sortedList[x].Name, StringComparison.OrdinalIgnoreCase) == 0).Priority = x; } // Detach from schema connection state change event oledbSchemaConnection.StateChange -= SchemaConnection_StateChange; // Check to see if user requested to keep connection open, this is just for convience... if (m_immediateClose) Close(); } /// /// state change event will fire if it unexpectedly close connection while processing. /// /// /// private void SchemaConnection_StateChange(object sender, StateChangeEventArgs e) { // The connection may have been closed prematurely so we reopen it. if (m_schemaConnection.State == ConnectionState.Closed) m_schemaConnection.Open(); } /// /// Close /// public void Close() { if ((object)m_schemaConnection != null) { try { m_schemaConnection.Close(); } catch { // Keep on going here... } } m_schemaConnection = null; } #endregion #region [ Static ] // Static Methods public static IDbConnection OpenConnection(string connectionString) { DatabaseType databaseType; Schema schema; bool isAdoConnection; return OpenConnection(connectionString, out databaseType, out schema, out isAdoConnection); } public static IDbConnection OpenConnection(string connectionString, out DatabaseType databaseType, out Schema deserializedSchema, out bool isAdoConnection) { Dictionary settings = connectionString.ParseKeyValuePairs(); deserializedSchema = null; databaseType = DatabaseType.Other; isAdoConnection = false; if (settings.ContainsKey("DataProviderString")) { // Assuming ADO connection string dataProviderString = settings["DataProviderString"]; settings.Remove("DataProviderString"); if (settings.ContainsKey("serializedSchema")) { string serializedSchemaFileName = FilePath.GetAbsolutePath(settings["serializedSchema"]); if (File.Exists(serializedSchemaFileName)) { using (FileStream stream = new FileStream(serializedSchemaFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { deserializedSchema = Serialization.Deserialize(stream, SerializationFormat.Binary); } } settings.Remove("serializedSchema"); } // Create updated connection string with removed settings connectionString = settings.JoinKeyValuePairs(); AdoDataConnection database = new AdoDataConnection(connectionString, dataProviderString); databaseType = database.DatabaseType; isAdoConnection = true; return database.Connection; } // Assuming OLEDB connection OleDbConnection connection = new OleDbConnection(connectionString); connection.Open(); return connection; } #endregion } }