#region Usings using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.Sql; using ICSharpCode.Data.Core.Common; using ICSharpCode.Data.Core.Interfaces; using System.Collections.ObjectModel; using ICSharpCode.Data.Core.DatabaseObjects; using Oracle.DataAccess.Client; using System.Collections.Specialized; using ICSharpCode.Data.Core.Enums; using System.Threading; #endregion namespace ICSharpCode.Data.Oracle { public class OracleDatabaseDriver : DatabaseDriver { #region Consts //private const string _getTables = @"SELECT TABLE_SCHEMA, TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME<>'dtproperties' ORDER BY TABLE_SCHEMA, TABLE_NAME"; private const string _getTables = @"SELECT USER AS TABLE_SCHEMA,TNAME AS TABLE_NAME FROM TAB WHERE TABTYPE='TABLE'"; //在Oracle中检索当前用户的所有表 // private const string _getColumnsScript = @"DECLARE @tablename varchar(100) SET @tablename = N'{0}' // SELECT // clmns.column_id AS [ColumnId], // clmns.name AS [Name], // usrt.name AS [DataType], // ISNULL(baset.name, N'') AS [SystemType], // CAST(CASE WHEN baset.name IN (N'nchar', N'nvarchar') AND clmns.max_length <> -1 THEN // clmns.max_length/2 ELSE 0 END AS INT) AS [Length], // CAST(clmns.precision AS int) AS [NumericPrecision], // clmns.default_object_id AS [DefaultObjectId], // clmns.is_ansi_padded AS [IsAnsiPadded], // // clmns.is_computed AS [IsComputed], // clmns.is_dts_replicated AS [IsDtsReplicated], // clmns.is_filestream AS [IsFileStream], // clmns.is_identity AS [IsIdentity], // clmns.is_merge_published AS [IsMergePublished], // clmns.is_non_sql_subscribed AS [IsNonSqlSubscribed], // clmns.is_nullable AS [IsNullable], // clmns.is_replicated AS [IsReplicated], // clmns.is_rowguidcol AS [IsRowGuidCol], // clmns.is_sparse AS [IsSparse], // clmns.is_xml_document AS [IsXmlDocument], // clmns.object_id AS [ObjectId], // clmns.rule_object_id AS [RuleObjectId], // clmns.scale AS [Scale], // clmns.system_type_id AS [SystemTypeId], // clmns.user_type_id AS [UserTypeId], // clmns.xml_collection_id AS [XMLCollectionId], // CAST( // CASE WHEN ( // SELECT c.name AS ColumnName // FROM sys.key_constraints AS k // JOIN sys.tables AS t ON t.object_id = k.parent_object_id // JOIN sys.schemas AS s ON s.schema_id = t.schema_id // JOIN sys.index_columns AS ic ON ic.object_id = t.object_id AND ic.index_id = k.unique_index_id // JOIN sys.columns AS c ON c.object_id = t.object_id AND c.column_id = ic.column_id // WHERE t.name=@tablename AND c.name = clmns.name) // IS NULL THEN 0 ELSE 1 END AS BIT) AS [IsPrimaryKey] // FROM // sys.{1} AS tbl // INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id // LEFT OUTER JOIN sys.types AS usrt ON usrt.user_type_id = clmns.user_type_id // LEFT OUTER JOIN sys.types AS baset ON baset.user_type_id = clmns.system_type_id and // baset.user_type_id = baset.system_type_id // WHERE // (tbl.name=@tablename and SCHEMA_NAME(tbl.schema_id)=N'{2}') // ORDER BY // clmns.column_id ASC"; private const string _getColumnsScript = @"SELECT COLUMN_ID as ColumnId,COLUMN_NAME as Name,DATA_TYPE as DataType,DATA_TYPE as SystemType,DATA_LENGTH as Length,DATA_PRECISION as NumericPrecision,0 as IsAnsiPadded,0 as IsComputed,0 as LsDtsReplicated,0 as IsFileStream,0 as IsIdentity,0 as IsMergePublished,0 as IsNullable,0 as IsRowGuidCol,0 as IsSpares,0 as IsXmlDocument,0 as ObjectId,0 as RuleObjectId,0 as Scale,0 as SystemTypeId,0 as UserTypeId,0 as XMLCollectionId,0 as IsPrimaryKey FROM USER_TAB_COLUMNS WHERE TABLE_NAME='{0}' ORDER BY COLUMN_ID DESC"; // private const string _getConstraintsScript = @"SELECT // FKTable = FK.TABLE_NAME, // FKColumn = CU.COLUMN_NAME, // PKTable = PK.TABLE_NAME, // PKColumn = PT.COLUMN_NAME, // ConstraintName = C.CONSTRAINT_NAME // FROM // INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C // INNER JOIN // INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK // ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME // INNER JOIN // INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK // ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME // INNER JOIN // INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU // ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME // INNER JOIN // ( // SELECT // i1.TABLE_NAME, i2.COLUMN_NAME // FROM // INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1 // INNER JOIN // INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 // ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME // WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY' // ) PT // ON PT.TABLE_NAME = PK.TABLE_NAME // -- optional: // ORDER BY // 1,2,3,4"; //private const string _getViews = @"SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='VIEW' AND TABLE_NAME<>'dtproperties' ORDER BY TABLE_SCHEMA, TABLE_NAME"; private const string _getViews = @"SELECT USER as TABLE_SCHEMA, TNAME as TABLE_NAME FROM TAB WHERE TABTYPE='VIEW' ORDER BY TABLE_SCHEMA, TABLE_NAME"; //private const string _getViewDefiningQuery = @"EXEC sp_helptext '{0}'"; //private const string _getProcedures = "SELECT ROUTINE_NAME, ROUTINE_SCHEMA, ROUTINE_BODY, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 'PROCEDURE'"; private const string _getProcedures = "SELECT PROCEDURE_NAME as ROUTINE_NAME, USER as ROUTINE_SCHEMA, 'SQL' as ROUTINE_BODY, NULL as DATA_TYPE, NULL as CHARACTER_MAXIMUM_LENGTH FROM USER_PROCEDURES WHERE PROCEDURE_NAME is not null"; //private const string _getProcedureParameters = @"SELECT PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, PARAMETER_MODE, IS_RESULT FROM information_schema.PARAMETERS WHERE SPECIFIC_NAME = '{0}' AND SPECIFIC_SCHEMA = '{1}' AND SPECIFIC_CATALOG = '{2}'"; #endregion public OracleDatabaseDriver() { Datasources = new DatabaseObjectsCollection(null); } public override string Name { get { return "Oracle"; } } public override string ProviderName { get { return "Oracle.DataAccess.Client"; } } public override string ODBCProviderName { get { return "Oracle11.2G"; } } public override void PopulateDatasources() { DatabaseObjectsCollection datasources = new DatabaseObjectsCollection(null); DataTable dt = SqlDataSourceEnumerator.Instance.GetDataSources(); foreach (DataRow dr in dt.Rows) { string serverName = dr["ServerName"].ToString().Trim().ToUpper(); string instanceName = null; Version version = null; if (dr["InstanceName"] != null && dr["InstanceName"] != DBNull.Value) instanceName = dr["InstanceName"].ToString().Trim().ToUpper(); if (dr["Version"] != null && dr["Version"] != DBNull.Value) version = new Version(dr["Version"].ToString().Trim()); OracleDatasource datasource = new OracleDatasource(this) { Name = serverName }; datasource.ProviderManifestToken = GetManifestToken(version); if (!String.IsNullOrEmpty(instanceName)) datasource.Name += "\\" + instanceName; datasources.Add(datasource); } Datasources = datasources; } string GetManifestToken(Version version) { string manifestToken; if (!IsVersionSupported(version, out manifestToken)) throw new NotSupportedException(string.Format("Version '{0}' is not supported!", version == null ? "unknown" : version.ToString())); return manifestToken; } bool IsVersionSupported(Version version, out string manifestToken) { manifestToken = ""; if (version == null) return false; switch (version.Major) { case 8: manifestToken = "8i"; return true; case 9: manifestToken = "9i"; return true; case 10: manifestToken = "10G"; return true; case 11: manifestToken = "11G"; return true; case 12: manifestToken = "12C"; return true; } return false; } public override void PopulateDatabases(IDatasource datasource) { DatabaseObjectsCollection databases = new DatabaseObjectsCollection(datasource); OracleConnection oracleConnection = null; oracleConnection = new OracleConnection(); oracleConnection.ConnectionString = datasource.ConnectionString; try { oracleConnection.Open(); } catch (OracleException ex) { switch (ex.Number) { case 2: case 3: case 53: new Thread(new ThreadStart(delegate() { Datasources.Remove(datasource as OracleDatasource); })).Start(); break; default: break; } ICSharpCode.Core.LoggingService.Error(ex.Message); ICSharpCode.Core.LoggingService.Error(ex.StackTrace); return; //throw ex; } string strVersion = oracleConnection.ServerVersion; string[] vs = strVersion.Split(new char[] { '.' }); if (vs.Length > 4) { strVersion = strVersion.Substring(0, strVersion.LastIndexOf(".")); } Version version = new Version(strVersion); datasource.ProviderManifestToken = GetManifestToken(version); string sql = "select name from v$database"; OracleCommand oracleCommand = new OracleCommand(sql, oracleConnection); oracleCommand.CommandTimeout = 20; OracleDataReader oracleDataReader = oracleCommand.ExecuteReader(); while (oracleDataReader.Read()) { databases.Add(new Database(datasource) { Name = oracleDataReader["name"].ToString() }); } oracleDataReader.Close(); datasource.Databases = databases; if (oracleConnection != null && oracleConnection.State == ConnectionState.Open) oracleConnection.Close(); } private void LoadColumns2(string version, OracleConnection oracleConnection, ITable table, TableType tableType) { //database.Datasource.ProviderManifestToken string tableTypeName = "tables"; if (tableType == TableType.View) tableTypeName = "views"; string getColumnsScript = _getColumnsScript; using (OracleDataAdapter dataAdapter = new OracleDataAdapter(string.Format(getColumnsScript, table.TableName, tableTypeName, table.SchemaName), oracleConnection)) { DataTable dtColumns = new DataTable("Columns"); dataAdapter.Fill(dtColumns); for (int j = 0; j < dtColumns.Rows.Count; j++) { Column column = new Column(table); column.ColumnId = Convert.ToInt32(dtColumns.Rows[j]["ColumnId"]); column.Name = (string)dtColumns.Rows[j]["Name"]; column.DataType = (string)dtColumns.Rows[j]["DataType"]; column.SystemType = (string)dtColumns.Rows[j]["SystemType"]; column.Length = Convert.ToInt32(dtColumns.Rows[j]["Length"]); if (column.Length == -1) { switch (column.DataType.ToLower()) { case "varchar": case "nvarchar": case "varchar2": column.DataType += "(max)"; break; default: break; } switch (column.SystemType.ToLower()) { case "varchar": case "nvarchar": case "varchar2": column.SystemType += "(max)"; break; default: break; } } object objNumericPrecision = dtColumns.Rows[j]["NumericPrecision"]; if (objNumericPrecision != null && objNumericPrecision != System.DBNull.Value) { column.Precision = Convert.ToInt32(objNumericPrecision); } else { column.Precision = 0; } object objScale = dtColumns.Rows[j]["Scale"]; if (objScale != null && objScale != System.DBNull.Value) { column.Scale = Convert.ToInt32(objScale); } else { column.Scale = 0; } object objIsIdentity = dtColumns.Rows[j]["IsIdentity"]; if (objIsIdentity != null && objIsIdentity != System.DBNull.Value) { column.IsIdentity = Convert.ToBoolean(objIsIdentity); } else { column.IsIdentity = false; } object objIsNullable = dtColumns.Rows[j]["IsNullable"]; if (objIsNullable != null && objIsNullable != System.DBNull.Value) { column.IsNullable = Convert.ToBoolean(objIsNullable); } else { column.IsNullable = false; } object objIsPrimaryKey = dtColumns.Rows[j]["IsPrimaryKey"]; if (objIsPrimaryKey != null && objIsPrimaryKey != System.DBNull.Value) { column.IsPrimaryKey = Convert.ToBoolean(objIsPrimaryKey); } else { column.IsPrimaryKey = false; } table.Items.Add(column); } } } private void LoadColumns(OracleConnection oracleConnection, ITable table, TableType tableType) { //datasource.ProviderManifestToken string tableTypeName = "tables"; if (tableType == TableType.View) tableTypeName = "views"; using (OracleDataAdapter dataAdapter = new OracleDataAdapter(string.Format(_getColumnsScript, table.TableName, tableTypeName, table.SchemaName), oracleConnection)) { DataTable dtColumns = new DataTable("Columns"); dataAdapter.Fill(dtColumns); for (int j = 0; j < dtColumns.Rows.Count; j++) { Column column = new Column(table); column.ColumnId = (int)dtColumns.Rows[j]["ColumnId"]; column.Name = (string)dtColumns.Rows[j]["Name"]; column.DataType = (string)dtColumns.Rows[j]["DataType"]; column.SystemType = (string)dtColumns.Rows[j]["SystemType"]; column.Length = Convert.ToInt32(dtColumns.Rows[j]["Length"]); if (column.Length == -1) { switch (column.DataType.ToLower()) { case "varchar": case "nvarchar": case "varchar2": column.DataType += "(max)"; break; default: break; } switch (column.SystemType.ToLower()) { case "varchar": case "nvarchar": case "varchar2": column.SystemType += "(max)"; break; default: break; } } column.Precision = Convert.ToInt32(dtColumns.Rows[j]["NumericPrecision"]); column.Scale = Convert.ToInt32(dtColumns.Rows[j]["Scale"]); column.IsIdentity = (bool)dtColumns.Rows[j]["IsIdentity"]; column.IsNullable = (bool)dtColumns.Rows[j]["IsNullable"]; column.IsPrimaryKey = (bool)dtColumns.Rows[j]["IsPrimaryKey"]; table.Items.Add(column); } } } public override DatabaseObjectsCollection LoadTables(IDatabase database) { DatabaseObjectsCollection tables = new DatabaseObjectsCollection(database); OracleConnection oracleConnection = new OracleConnection(database.ConnectionString); #region 把获取约束的代码注释掉 //using (OracleDataAdapter da = new OracleDataAdapter(_getConstraintsScript, oracleConnection)) //{ // DataTable dtConstraints = new DataTable("Constraints"); // da.Fill(dtConstraints); // for (int i = 0; i < dtConstraints.Rows.Count; i++) // { // string constraintName = (string)dtConstraints.Rows[i]["ConstraintName"]; // if (database.Constraints.Count > 0) // { // IConstraint constraint = database.Constraints.FirstOrDefault(c => c.Name == constraintName); // if (constraint == null) // { // constraint = new ICSharpCode.Data.Core.DatabaseObjects.Constraint(); // constraint.Name = constraintName; // constraint.FKTableName = (string)dtConstraints.Rows[i]["FKTable"]; // constraint.PKTableName = (string)dtConstraints.Rows[i]["PKTable"]; // database.Constraints.Add(constraint); // } // constraint.FKColumnNames.Add((string)dtConstraints.Rows[i]["FKColumn"]); // constraint.PKColumnNames.Add((string)dtConstraints.Rows[i]["PKColumn"]); // } // } //} #endregion using (OracleDataAdapter da = new OracleDataAdapter(_getTables, oracleConnection)) { DataTable dtTables = new DataTable("Tables"); da.Fill(dtTables); for (int i = 0; i < dtTables.Rows.Count; i++) { string schemaName = (string)dtTables.Rows[i]["TABLE_SCHEMA"]; string tableName = (string)dtTables.Rows[i]["TABLE_NAME"]; Table table = new Table() { SchemaName = schemaName, TableName = tableName }; //LoadColumns(sqlConnection, table, TableType.Table); LoadColumns2(database.Datasource.ProviderManifestToken, oracleConnection, table, TableType.Table); table.Constraints = database.Constraints.Where(constraint => constraint.FKTableName == tableName).ToDatabaseObjectsCollection(table); tables.Add(table); } } return tables; } public override DatabaseObjectsCollection LoadViews(IDatabase database) { DatabaseObjectsCollection views = new DatabaseObjectsCollection(database); OracleConnection oracleConnection = new OracleConnection(database.ConnectionString); using (OracleDataAdapter da = new OracleDataAdapter(_getViews, oracleConnection)) { DataTable dtViews = new DataTable("Views"); da.Fill(dtViews); for (int i = 0; i < dtViews.Rows.Count; i++) { string schemaName = (string)dtViews.Rows[i]["TABLE_SCHEMA"]; string viewName = (string)dtViews.Rows[i]["TABLE_NAME"]; View view = new View() { SchemaName = schemaName, TableName = viewName, Query = LoadViewQuery(oracleConnection, schemaName, viewName) }; //LoadColumns(sqlConnection, view, TableType.View); LoadColumns2(database.Datasource.ProviderManifestToken, oracleConnection, view, TableType.View); views.Add(view); } } return views; } private string LoadViewQuery(OracleConnection oracleConnection, string schemaName, string tableName) { string definingQuery = string.Empty; #region 注释掉获取视图定义语句的代码 //using (OracleDataAdapter dataAdapter = // new OracleDataAdapter(string.Format(_getViewDefiningQuery, schemaName + "." + tableName), oracleConnection)) //{ // DataTable dtQuery = new DataTable("Text"); // dataAdapter.Fill(dtQuery); // for (int i = 0; i < dtQuery.Rows.Count; i++) // { // definingQuery += (string)dtQuery.Rows[i]["Text"]; // } //} #endregion return definingQuery; } public override DatabaseObjectsCollection LoadProcedures(IDatabase database) { DatabaseObjectsCollection procedures = new DatabaseObjectsCollection(database); OracleConnection oracleConnection = new OracleConnection(database.ConnectionString); using (OracleDataAdapter da = new OracleDataAdapter(_getProcedures, oracleConnection)) { DataTable dtProcedures = new DataTable("Procedures"); da.Fill(dtProcedures); for (int i = 0; i < dtProcedures.Rows.Count; i++) { Procedure procedure = new Procedure(); procedure.Name = dtProcedures.Rows[i]["ROUTINE_NAME"] as string; procedure.SchemaName = dtProcedures.Rows[i]["ROUTINE_SCHEMA"] as string; if (dtProcedures.Rows[i]["DATA_TYPE"] != DBNull.Value) procedure.DataType = (string)dtProcedures.Rows[i]["DATA_TYPE"]; if (dtProcedures.Rows[i]["CHARACTER_MAXIMUM_LENGTH"] != DBNull.Value) procedure.Length = Convert.ToInt32(dtProcedures.Rows[i]["CHARACTER_MAXIMUM_LENGTH"]); if (procedure.Length == -1) { switch (procedure.DataType.ToLower()) { case "varchar": case "nvarchar": case "varchar2": procedure.DataType += "(max)"; break; default: break; } } string procedureType = dtProcedures.Rows[i]["ROUTINE_BODY"] as string; if (procedureType == "SQL") procedure.ProcedureType = ProcedureType.SQL; else procedure.ProcedureType = ProcedureType.External; #region 注释掉获取存储过程参数的代码 //procedure.Items = new DatabaseObjectsCollection(procedure); //DatabaseObjectsCollection procedureParameters = new DatabaseObjectsCollection(procedure); //da.SelectCommand = new OracleCommand(string.Format(_getProcedureParameters, procedure.Name, procedure.SchemaName, database.Name), oracleConnection); //DataTable dtProcedureParameters = new DataTable("ProcedureParameters"); //da.Fill(dtProcedureParameters); //for (int j = 0; j < dtProcedureParameters.Rows.Count; j++) //{ // if (string.IsNullOrEmpty((string)dtProcedureParameters.Rows[j]["PARAMETER_NAME"]) && // (string)dtProcedureParameters.Rows[j]["IS_RESULT"] == "YES") // = ReturnValue // continue; // ProcedureParameter procedureParameter = new ProcedureParameter(); // procedureParameter.Name = (string)dtProcedureParameters.Rows[j]["PARAMETER_NAME"]; // if (procedureParameter.Name.StartsWith("@")) // procedureParameter.Name = procedureParameter.Name.Substring(1); // if (dtProcedureParameters.Rows[j]["DATA_TYPE"] != DBNull.Value) // procedureParameter.DataType = (string)dtProcedureParameters.Rows[j]["DATA_TYPE"]; // if (dtProcedureParameters.Rows[j]["CHARACTER_MAXIMUM_LENGTH"] != DBNull.Value) // procedureParameter.Length = Convert.ToInt32(dtProcedureParameters.Rows[j]["CHARACTER_MAXIMUM_LENGTH"]); // string parameterMode = (string)dtProcedureParameters.Rows[j]["PARAMETER_MODE"]; // if (parameterMode == "IN") // procedureParameter.ParameterMode = ParameterMode.In; // else if (parameterMode == "OUT") // procedureParameter.ParameterMode = ParameterMode.Out; // else // procedureParameter.ParameterMode = ParameterMode.InOut; // procedure.Items.Add(procedureParameter); //} #endregion procedures.Add(procedure); } } return procedures; } public override string ToString() { return this.Name; } public override IDatasource CreateNewIDatasource( string server , string userid , string password ) { OracleDatasource ds = new OracleDatasource(this); //connectionString//Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.19.129)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)));User Id=system;Password=oracle; ds.Name = server; ds.Server = server; ds.UserId = userid; ds.Password = password; return ds; } } }