diff --git a/VAR.DatabaseExplorer/Code/BusinessLogic/DatabaseBL.cs b/VAR.DatabaseExplorer/Code/BusinessLogic/DatabaseBL.cs index 902b239..324b49e 100644 --- a/VAR.DatabaseExplorer/Code/BusinessLogic/DatabaseBL.cs +++ b/VAR.DatabaseExplorer/Code/BusinessLogic/DatabaseBL.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using System.Linq; using VAR.DatabaseExplorer.Code.DataAccess; using VAR.DatabaseExplorer.Code.DataTransfer; @@ -72,40 +73,29 @@ namespace VAR.DatabaseExplorer.Code.BusinessLogic // Desactivar todas las FKs txtWriter.WriteLine("-- Disable all constraints"); - foreach (Table t in database.Tables) + foreach (Table table in database.Tables) { - if (t.Type != "BASE TABLE") { continue; } + if (table.Type != "BASE TABLE") { continue; } - string tableName = string.Format("[{0}].[{1}]", t.Schema, t.Name); + string tableName = string.Format("[{0}].[{1}]", table.Schema, table.Name); txtWriter.WriteLine(string.Format("ALTER TABLE {0} NOCHECK CONSTRAINT all;", tableName)); } txtWriter.WriteLine("GO"); txtWriter.WriteLine(string.Empty); // Prepara información a exportar - foreach (Table t in database.Tables) + foreach (Table table in database.Tables) { - if (t.Type != "BASE TABLE") { continue; } - - string tableName = string.Format("{0}.{1}", t.Schema, t.Name); - txtWriter.WriteLine(string.Format("PRINT '*** Importing data of {0}....';", tableName)); - if (t.Columns.Any(c => c.Indentity)) - { - TableBL.Table_ExportDataWithIdentity(t, txtWriter, connectionString, tableName); - } - else - { - TableBL.Table_ExportData(t, txtWriter, connectionString, tableName); - } + TableBL.Table_ExportData(table, txtWriter, connectionString); } // Activar todas las FKs txtWriter.WriteLine("-- Enable all constraints"); - foreach (Table t in database.Tables) + foreach (Table table in database.Tables) { - if (t.Type != "BASE TABLE") { continue; } + if (table.Type != "BASE TABLE") { continue; } - string tableName = string.Format("[{0}].[{1}]", t.Schema, t.Name); + string tableName = string.Format("[{0}].[{1}]", table.Schema, table.Name); txtWriter.WriteLine(string.Format("ALTER TABLE {0} WITH CHECK CHECK CONSTRAINT all;", tableName)); } txtWriter.WriteLine("GO"); @@ -114,70 +104,36 @@ namespace VAR.DatabaseExplorer.Code.BusinessLogic public static void Database_ExportTables(TextWriter txtWriter, string connectionString, Database database) { - foreach (Table t in database.Tables) + foreach (Table table in database.Tables) { - if (t.Type != "BASE TABLE") { continue; } - - string tableName = string.Format("{0}.{1}", t.Schema, t.Name); - txtWriter.WriteLine(string.Format("PRINT '*** Creating tabla {0}....';", tableName)); - - txtWriter.WriteLine(string.Format("CREATE TABLE {0} (", tableName)); - bool firstColumn = true; - foreach (Column c in t.Columns) - { - if (firstColumn == false) - { - txtWriter.WriteLine(","); - } - txtWriter.Write(" ["); - txtWriter.Write(c.Name); - txtWriter.Write("] "); - if ( - c.Type == "nvarchar" || - c.Type == "varchar" || - c.Type == "char" || - c.Type == "nchar" || - c.Type == "binary" || - c.Type == "varbinary" || - c.Type == "image") - { - if (c.Size < 0) - { - txtWriter.Write(string.Format("{0}(MAX)", c.Type)); - } - else - { - txtWriter.Write(string.Format("{0}({1})", c.Type, c.Size)); - } - } - else - { - txtWriter.Write(c.Type); - } - if (c.Nullable) - { - txtWriter.Write(" NULL"); - } - else - { - txtWriter.Write(" NOT NULL"); - } - if (c.PK) - { - txtWriter.Write(" PRIMARY KEY"); - } - if (c.Indentity) - { - txtWriter.Write(" IDENTITY(1,1)"); - } - firstColumn = false; - - } - txtWriter.WriteLine(); - txtWriter.WriteLine(string.Format(");")); - txtWriter.WriteLine("GO"); - txtWriter.WriteLine(); + TableBL.Table_GenerateCreate(table, txtWriter); } } + + public static void Database_ExportFunctions(StreamWriter txtWriter, Database database) + { + List exportedRoutines = new List(); + + int exportedOnLoopCount = 0; + do + { + exportedOnLoopCount = 0; + foreach (Procedure routine in database.Procedures) + { + if (exportedRoutines.Any(er => er.Schema == routine.Schema && er.Name == routine.Name)) { continue; } + if (routine.Dependencies.Count > 0) + { + if (routine.Dependencies.Any(pd => exportedRoutines.Any(er => er.Schema == pd.Schema && er.Name == pd.Name) == false)) + { + continue; + } + } + + ProcedureBL.Procedure_GenerateCreate(routine, txtWriter); + exportedRoutines.Add(routine); + exportedOnLoopCount++; + } + } while (exportedOnLoopCount > 0); + } } } \ No newline at end of file diff --git a/VAR.DatabaseExplorer/Code/BusinessLogic/ProcedureBL.cs b/VAR.DatabaseExplorer/Code/BusinessLogic/ProcedureBL.cs index 73e9a07..51b870b 100644 --- a/VAR.DatabaseExplorer/Code/BusinessLogic/ProcedureBL.cs +++ b/VAR.DatabaseExplorer/Code/BusinessLogic/ProcedureBL.cs @@ -1,4 +1,7 @@ using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; using VAR.DatabaseExplorer.Code.DataAccess; using VAR.DatabaseExplorer.Code.DataTransfer; @@ -11,12 +14,105 @@ namespace VAR.DatabaseExplorer.Code.BusinessLogic List procedures = ProcedureDA.GetAllProcedures(connectionString); if (fillDefinition) { + // Get all definitions + List definitions = ProcedureDA.GetProcedureDefinitions(connectionString, null, null); foreach (Procedure procedure in procedures) { - procedure.Definition = ProcedureDA.GetProcedureDefinition(connectionString, procedure.Schema, procedure.Name); + var sbDefinition = new StringBuilder(); + foreach (ProcedureDefinition definition in definitions) + { + if (procedure.Schema == definition.ProcedureSchema && procedure.Name == definition.ProcedureName) + { + sbDefinition.Append(definition.Definition); + } + } + procedure.Definition = sbDefinition.ToString(); } + Procedure_AssingDependencies(procedures); } return procedures; } + + private static void Procedure_AssignDependency(Procedure procedure, Procedure procedureDep) + { + if (procedure.Dependencies.Any(pd => procedureDep.Schema == pd.Schema && procedureDep.Name == pd.Name)) { return; } + procedure.Dependencies.Add(procedureDep); + } + + private static void Procedure_CheckDependencies(IEnumerable procedures, Procedure procedureDep, string strProcFullName) + { + foreach (Procedure procedure in procedures) + { + if (procedure.Schema == procedureDep.Schema && procedure.Name == procedureDep.Name) { continue; } + + if (string.IsNullOrEmpty(procedure.DefinitionLowercase)) + { + procedure.DefinitionLowercase = procedure.Definition.ToLower(); + } + if (procedure.DefinitionLowercase.Contains(strProcFullName)) + { + Procedure_AssignDependency(procedure, procedureDep); + } + } + } + + private static void Procedure_AssingDependencies(IEnumerable procedures) + { + foreach (Procedure procedureDep in procedures) + { + string strProcFullName; + string strProcedureSchema = procedureDep.Schema.ToLower(); + string strProcedureName = procedureDep.Name.ToLower(); + + strProcFullName = string.Format("{0}.{1} ", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("{0}.{1}(", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + + strProcFullName = string.Format("[{0}].{1} ", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("[{0}].{1}(", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("{0}.[{1}]", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("[{0}].[{1}]", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + + strProcFullName = string.Format("\"{0}\".{1} ", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("\"{0}\".{1}(", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("{0}.\"{1}\"", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + strProcFullName = string.Format("\"{0}\".\"{1}\"", strProcedureSchema, strProcedureName); + Procedure_CheckDependencies(procedures, procedureDep, strProcFullName); + } + } + + internal static void Procedure_GenerateCreate(Procedure routine, StreamWriter txtWriter) + { + string routineName = string.Format("{0}.{1}", routine.Schema, routine.Name); + if (routine.Type.ToUpper() == "PROCEDURE") + { + txtWriter.WriteLine(string.Format("PRINT '*** Creating procedure {0}....';", routineName)); + txtWriter.WriteLine(string.Format("IF EXISTS (SELECT TOP 1 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = '{0}' AND ROUTINE_NAME = '{1}')", routine.Schema, routine.Name)); + txtWriter.WriteLine("BEGIN"); + txtWriter.WriteLine(string.Format(" DROP PROCEDURE {0};", routineName)); + txtWriter.WriteLine("END"); + } + if (routine.Type.ToUpper() == "FUNCTION") + { + txtWriter.WriteLine(string.Format("PRINT '*** Creating function {0}....';", routineName)); + txtWriter.WriteLine(string.Format("IF EXISTS (SELECT TOP 1 1 FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = '{0}' AND ROUTINE_NAME = '{1}')", routine.Schema, routine.Name)); + txtWriter.WriteLine("BEGIN"); + txtWriter.WriteLine(string.Format(" DROP FUNCTION {0};", routineName)); + txtWriter.WriteLine("END"); + } + + txtWriter.WriteLine("GO"); + txtWriter.WriteLine(routine.Definition); + txtWriter.WriteLine("GO"); + txtWriter.WriteLine(); + } } } \ No newline at end of file diff --git a/VAR.DatabaseExplorer/Code/BusinessLogic/TableBL.cs b/VAR.DatabaseExplorer/Code/BusinessLogic/TableBL.cs index 1f3c5c4..ded5da1 100644 --- a/VAR.DatabaseExplorer/Code/BusinessLogic/TableBL.cs +++ b/VAR.DatabaseExplorer/Code/BusinessLogic/TableBL.cs @@ -23,32 +23,105 @@ namespace VAR.DatabaseExplorer.Code.BusinessLogic return tables; } - public static void Table_ExportDataWithIdentity(Table t, TextWriter txtWriter, string conectionString, string tableFullName) + public static void Table_ExportData(Table t, TextWriter txtWriter, string conectionString) { - DataTable dtData = TableDA.GetData(conectionString, tableFullName); + if (t.Type != "BASE TABLE") { return; } - txtWriter.WriteLine(string.Format("-- {0}", tableFullName)); - txtWriter.WriteLine(string.Format("DELETE FROM {0};", tableFullName)); - txtWriter.WriteLine(string.Format("DBCC CHECKIDENT ('{0}', RESEED, 0);", tableFullName)); - txtWriter.WriteLine(string.Format("SET IDENTITY_INSERT {0} ON;", tableFullName)); - txtWriter.WriteLine("GO"); - DataTableHelper.DataTable_GenerateInserts(txtWriter, dtData, tableFullName); - txtWriter.WriteLine("GO"); - txtWriter.WriteLine(string.Format("SET IDENTITY_INSERT {0} OFF;", tableFullName)); - txtWriter.WriteLine("GO"); - txtWriter.WriteLine(string.Empty); + string tableName = string.Format("{0}.{1}", t.Schema, t.Name); + txtWriter.WriteLine(string.Format("PRINT '*** Importing data of {0}....';", tableName)); + DataTable dtData = TableDA.GetData(conectionString, tableName); + if (t.Columns.Any(c => c.Indentity)) + { + txtWriter.WriteLine(string.Format("-- {0}", tableName)); + txtWriter.WriteLine(string.Format("DELETE FROM {0};", tableName)); + txtWriter.WriteLine(string.Format("DBCC CHECKIDENT ('{0}', RESEED, 0);", tableName)); + txtWriter.WriteLine(string.Format("SET IDENTITY_INSERT {0} ON;", tableName)); + txtWriter.WriteLine("GO"); + DataTableHelper.DataTable_GenerateInserts(txtWriter, dtData, tableName); + txtWriter.WriteLine("GO"); + txtWriter.WriteLine(string.Format("SET IDENTITY_INSERT {0} OFF;", tableName)); + txtWriter.WriteLine("GO"); + txtWriter.WriteLine(string.Empty); + } + else + { + txtWriter.WriteLine(string.Format("-- {0}", tableName)); + txtWriter.WriteLine(string.Format("DELETE FROM {0};", tableName)); + txtWriter.WriteLine("GO"); + DataTableHelper.DataTable_GenerateInserts(txtWriter, dtData, tableName); + txtWriter.WriteLine("GO"); + txtWriter.WriteLine(string.Empty); + } } - public static void Table_ExportData(Table t, TextWriter txtWriter, string conectionString, string tableFullName) + public static void Table_GenerateCreate(Table table, TextWriter txtWriter) { - DataTable dtData = TableDA.GetData(conectionString, tableFullName); + if (table.Type != "BASE TABLE") { return; } + + string tableName = string.Format("{0}.{1}", table.Schema, table.Name); + txtWriter.WriteLine(string.Format("PRINT '*** Creating tabla {0}....';", tableName)); + txtWriter.WriteLine(string.Format("IF EXISTS (SELECT TOP 1 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{0}' AND TABLE_NAME = '{1}')", table.Schema, table.Name)); + txtWriter.WriteLine("BEGIN"); + txtWriter.WriteLine(string.Format(" DROP TABLE {0};", tableName)); + txtWriter.WriteLine("END"); - txtWriter.WriteLine(string.Format("-- {0}", tableFullName)); - txtWriter.WriteLine(string.Format("DELETE FROM {0};", tableFullName)); txtWriter.WriteLine("GO"); - DataTableHelper.DataTable_GenerateInserts(txtWriter, dtData, tableFullName); + txtWriter.WriteLine(string.Format("CREATE TABLE {0} (", tableName)); + bool firstColumn = true; + foreach (Column c in table.Columns) + { + if (firstColumn == false) + { + txtWriter.WriteLine(","); + } + txtWriter.Write(" ["); + txtWriter.Write(c.Name); + txtWriter.Write("] "); + if ( + c.Type == "nvarchar" || + c.Type == "varchar" || + c.Type == "char" || + c.Type == "nchar" || + c.Type == "binary" || + c.Type == "varbinary" || + c.Type == "image") + { + if (c.Size < 0) + { + txtWriter.Write(string.Format("{0}(MAX)", c.Type)); + } + else + { + txtWriter.Write(string.Format("{0}({1})", c.Type, c.Size)); + } + } + else + { + txtWriter.Write(c.Type); + } + if (c.Nullable) + { + txtWriter.Write(" NULL"); + } + else + { + txtWriter.Write(" NOT NULL"); + } + if (c.PK) + { + txtWriter.Write(" PRIMARY KEY"); + } + if (c.Indentity) + { + txtWriter.Write(" IDENTITY(1,1)"); + } + firstColumn = false; + + } + txtWriter.WriteLine(); + txtWriter.WriteLine(string.Format(");")); txtWriter.WriteLine("GO"); - txtWriter.WriteLine(string.Empty); + txtWriter.WriteLine(); } } } \ No newline at end of file diff --git a/VAR.DatabaseExplorer/Code/DataAccess/ProcedureDA.cs b/VAR.DatabaseExplorer/Code/DataAccess/ProcedureDA.cs index 057480f..4328eb6 100644 --- a/VAR.DatabaseExplorer/Code/DataAccess/ProcedureDA.cs +++ b/VAR.DatabaseExplorer/Code/DataAccess/ProcedureDA.cs @@ -45,6 +45,8 @@ namespace VAR.DatabaseExplorer.Code.DataAccess { dataAdapter = new SqlDataAdapter(@" SELECT + sn.name ProcedureSchema, + sp.name ProcedureName, ISNULL(smsp.definition, ssmsp.definition) AS [Definition] FROM sys.all_objects AS sp INNER JOIN sys.schemas sn ON sp.schema_id = sn.schema_id @@ -53,7 +55,8 @@ namespace VAR.DatabaseExplorer.Code.DataAccess WHERE (sp.type = N'P' OR sp.type = N'RF' OR sp.type = N'PC' OR sp.type = N'IF' OR sp.type = N'FN' OR sp.type = N'TF') AND - (sp.name = @name and sn.name = @schema) + (@name IS NULL OR sp.name = @name) AND + (@schema IS NULL OR sn.name = @schema) ", cnx); dataAdapter.SelectCommand.Parameters.AddWithValue("@Name", name); dataAdapter.SelectCommand.Parameters.AddWithValue("@Schema", schema); @@ -78,5 +81,54 @@ namespace VAR.DatabaseExplorer.Code.DataAccess return sbProc.ToString(); } + + public static List GetProcedureDefinitions(string connectionString, string schema, string name) + { + SqlDataAdapter dataAdapter; + var cnx = new SqlConnection(connectionString); + cnx.Open(); + + if (cnx.ServerVersion.StartsWith("10.") || cnx.ServerVersion.StartsWith("11.")) + { + dataAdapter = new SqlDataAdapter(@" + SELECT + sn.name ProcedureSchema, + sp.name ProcedureName, + ISNULL(smsp.definition, ssmsp.definition) AS [Definition] + FROM sys.all_objects AS sp + INNER JOIN sys.schemas sn ON sp.schema_id = sn.schema_id + LEFT OUTER JOIN sys.sql_modules AS smsp ON smsp.object_id = sp.object_id + LEFT OUTER JOIN sys.system_sql_modules AS ssmsp ON ssmsp.object_id = sp.object_id + WHERE + (sp.type = N'P' OR sp.type = N'RF' OR sp.type = N'PC' OR sp.type = N'IF' OR sp.type = N'FN' OR sp.type = N'TF') + AND + (@name IS NULL OR sp.name = @name) AND + (@schema IS NULL OR sn.name = @schema) + ", cnx); + dataAdapter.SelectCommand.Parameters.AddWithValue("@Name", (object)name ?? DBNull.Value); + dataAdapter.SelectCommand.Parameters.AddWithValue("@Schema", (object)schema ?? DBNull.Value); + } + else + { + cnx.Close(); + return null; + } + + var dt = new DataTable(); + dataAdapter.Fill(dt); + cnx.Close(); + + var definitions = new List(); + foreach (DataRow dr in dt.Rows) + { + string strProcSchema = Convert.ToString(dr["ProcedureSchema"]); + string strProcName = Convert.ToString(dr["ProcedureName"]); + string strProcBlock = Convert.ToString(dr["Definition"]); + strProcBlock = strProcBlock.Replace("\r", "").Replace("\n", "\r\n"); + definitions.Add(new ProcedureDefinition { ProcedureSchema = strProcSchema, ProcedureName = strProcName, Definition = strProcBlock }); + } + + return definitions; + } } } \ No newline at end of file diff --git a/VAR.DatabaseExplorer/Code/DataTransfer/Procedure.cs b/VAR.DatabaseExplorer/Code/DataTransfer/Procedure.cs index 17d3a61..d7d9006 100644 --- a/VAR.DatabaseExplorer/Code/DataTransfer/Procedure.cs +++ b/VAR.DatabaseExplorer/Code/DataTransfer/Procedure.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Xml.Serialization; namespace VAR.DatabaseExplorer.Code.DataTransfer @@ -20,5 +21,11 @@ namespace VAR.DatabaseExplorer.Code.DataTransfer [XmlElement] public string Definition { get; set; } + + [XmlIgnore] + public string DefinitionLowercase { get; set; } + + [XmlIgnore] + public List Dependencies { get; } = new List(); } } \ No newline at end of file diff --git a/VAR.DatabaseExplorer/Code/DataTransfer/ProcedureDefinition.cs b/VAR.DatabaseExplorer/Code/DataTransfer/ProcedureDefinition.cs new file mode 100644 index 0000000..9d06da2 --- /dev/null +++ b/VAR.DatabaseExplorer/Code/DataTransfer/ProcedureDefinition.cs @@ -0,0 +1,9 @@ +namespace VAR.DatabaseExplorer.Code.DataTransfer +{ + public class ProcedureDefinition + { + public string ProcedureSchema { get; set; } + public string ProcedureName { get; set; } + public string Definition { get; set; } + } +} diff --git a/VAR.DatabaseExplorer/UI/FrmBaseDatos.cs b/VAR.DatabaseExplorer/UI/FrmBaseDatos.cs index d15b716..2ac293c 100644 --- a/VAR.DatabaseExplorer/UI/FrmBaseDatos.cs +++ b/VAR.DatabaseExplorer/UI/FrmBaseDatos.cs @@ -116,7 +116,7 @@ namespace VAR.DatabaseExplorer.UI Database database = DatabaseBL.Database_GetSchema(connectionString: _connectionString, fillTableDefinitions: true); string fixedDatabaseName = database.Name.Replace(' ', '_'); - var streamWriter = new StreamWriter(fixedDatabaseName + ".data.sql"); + var streamWriter = new StreamWriter(fixedDatabaseName + ".Data.sql"); DatabaseBL.Database_ExportData(streamWriter, _connectionString, database); streamWriter.Close(); @@ -127,21 +127,21 @@ namespace VAR.DatabaseExplorer.UI { Parent.Enabled = false; - Database database = DatabaseBL.Database_GetSchema(connectionString: _connectionString, fillTableDefinitions: true); + Database database = DatabaseBL.Database_GetSchema(connectionString: _connectionString, fillTableDefinitions: true, fillProcDefinitions: true); string fixedDatabaseName = database.Name.Replace(' ', '_'); // Tables - var streamWriter = new StreamWriter(fixedDatabaseName + ".Tables.sql"); - DatabaseBL.Database_ExportTables(streamWriter, _connectionString, database); - streamWriter.Close(); + var streamWriterTables = new StreamWriter(fixedDatabaseName + ".Tables.sql"); + DatabaseBL.Database_ExportTables(streamWriterTables, _connectionString, database); + streamWriterTables.Close(); - // TODO Functions + // Routines + var streamWriterRoutines = new StreamWriter(fixedDatabaseName + ".Routines.sql"); + DatabaseBL.Database_ExportFunctions(streamWriterRoutines, database); + streamWriterRoutines.Close(); // TODO Views - // TODO Procedures - - Parent.Enabled = true; } } diff --git a/VAR.DatabaseExplorer/VAR.DatabaseExplorer.csproj b/VAR.DatabaseExplorer/VAR.DatabaseExplorer.csproj index 70a18b0..224686e 100644 --- a/VAR.DatabaseExplorer/VAR.DatabaseExplorer.csproj +++ b/VAR.DatabaseExplorer/VAR.DatabaseExplorer.csproj @@ -91,6 +91,7 @@ +