using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Xml.Linq; using FluentMigrator; namespace Kreta.DataAccess.Migrations { public abstract class CustomMigration : Migration { #region Public methods public void SchemaUpdateRegisteredSPFN() { Execute.Sql("EXEC [dev].[uspSchemaUpdateRegisteredSPFN]"); } public void RunAllScriptsOnDboAndDev() { string migrationsBasePathForDbo = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "DBScripts", "Database", "dbo"); string[] devScripts = Directory.GetFiles( Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "DBScripts", "Database", "dev"), "*.sql", SearchOption.TopDirectoryOnly); foreach (string devScriptName in devScripts) { Execute.Script(devScriptName); } string functionsBasePath = Path.Combine(migrationsBasePathForDbo, "Functions"); List sqlFunctionFilesPath = Directory.GetFiles( functionsBasePath, "*.sql", SearchOption.TopDirectoryOnly) .ToList(); IEnumerable firstFunctions = File.ReadLines(Path.Combine(functionsBasePath, "FunctionOrder.txt")); string[] sqlStoredProcedureFilesPath = Directory.GetFiles( Path.Combine(migrationsBasePathForDbo, "Stored procedures"), "*.sql", SearchOption.TopDirectoryOnly); foreach (string functionsFileName in firstFunctions) { string functionPath = Path.Combine(functionsBasePath, functionsFileName); sqlFunctionFilesPath.Remove(functionPath); Execute.Script(functionPath); } foreach (string sqlFunctionFilePath in sqlFunctionFilesPath) { Execute.Script(sqlFunctionFilePath); } foreach (string sqlStoredProcedureFilePath in sqlStoredProcedureFilesPath) { Execute.Script(sqlStoredProcedureFilePath); } } public void RegisterSPFN(params string[] sqlFileNames) { if (sqlFileNames.Length == 0) { return; } bool? isStoredProcedure; var errorMessages = new List(); Type migrationType = GetType(); MigrationAttribute migrationAttribute = migrationType.GetCustomAttributes(typeof(MigrationAttribute), true).OfType().Single(); long migrationVersion = migrationAttribute.Version; string migrationName = migrationType.Name; string baseDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "DBScripts", "Database", "dbo"); foreach (string sqlFileName in sqlFileNames) { isStoredProcedure = IsStoredProcedure(sqlFileName, errorMessages); if (isStoredProcedure.HasValue) { if (File.Exists(Path.Combine(baseDirectory, isStoredProcedure.Value ? "Stored procedures" : "Functions", $"{sqlFileName}.sql"))) { Execute.Sql($"EXEC [dev].[uspRegisterSPFN] '{sqlFileName}', {(isStoredProcedure.Value ? 1 : 0)}"); } else { errorMessages.Add($"Ilyen nevű stored procedure vagy function {sqlFileName} nem található a DBScripts mappában!"); WriteErrorToConsole(errorMessages, migrationVersion, migrationName); } } else { WriteErrorToConsole(errorMessages, migrationVersion, migrationName); } } } public void ExecuteScripts(params string[] sqlFileNames) { if (sqlFileNames.Length == 0) { return; } Type migrationType = GetType(); MigrationAttribute migrationAttribute = migrationType.GetCustomAttributes(typeof(MigrationAttribute), true).OfType().Single(); string migrationName = migrationType.Name; string assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string baseDirectory = Path.Combine(assemblyDirectory, "Scripts", $"{migrationAttribute.Version}_{migrationName}"); string baseArchiveDirectory = Path.Combine(assemblyDirectory, "Scripts", "Archive", $"{migrationAttribute.Version}_{migrationName}"); foreach (string sqlFileName in sqlFileNames) { string sqlFilePath = Path.Combine(baseDirectory, sqlFileName); if (!File.Exists(sqlFilePath)) { sqlFilePath = Path.Combine(baseArchiveDirectory, sqlFileName); } Execute.Script(sqlFilePath); } } public void CreateSchemaSPFN(params string[] spfnList) { if (spfnList.Length == 0) { return; } Execute.Sql($"EXEC [dev].[uspCreateSchemaSPFN] '{string.Join(",", spfnList)}'"); } public void DropSchemaSPFN(params string[] spfnList) { if (spfnList.Length == 0) { return; } Execute.Sql($"EXEC [dev].[uspDropSchemaSPFN] '{string.Join(",", spfnList)}'"); } public void CreateSchemaStoredProcedures(params string[] storedProcedureNames) { CreateSchemaSPFN(storedProcedureNames); } public void CreateSchemaFunctions(params string[] functionNames) { CreateSchemaSPFN(functionNames); } public void DeleteViews(params string[] viewNames) { if (viewNames.Length == 0) { return; } Execute.Sql($"EXEC [dev].[uspDropSchemaViews] '{string.Join(",", viewNames)}'"); } public void DeleteStoredProcedures(params string[] storedProcedureNames) { DropSchemaSPFN(storedProcedureNames); } public void DeleteFunctions(params string[] functionNames) { DropSchemaSPFN(functionNames); } #endregion #region Private methods private bool? IsStoredProcedure(string sqlFileName, List errorMessages) { if (sqlFileName.StartsWith("sp_", StringComparison.OrdinalIgnoreCase) || sqlFileName.StartsWith("usp", StringComparison.OrdinalIgnoreCase)) { return true; } if (sqlFileName.StartsWith("fn", StringComparison.OrdinalIgnoreCase)) { return false; } errorMessages.Add($"Nem felel meg az elnevezési konvekcióknak: {sqlFileName}"); return null; } private void WriteErrorToConsole(List errorMessages, long migrationVersion, string migrationName) { if (errorMessages.Any()) { //Execute.Sql($"DELETE FROM [dbo].[VersionInfo] WHERE Description = 'TESZT'"); throw new Exception($"Hibás migráció: {migrationVersion}_{migrationName}: {errorMessages[0]}"); } } private void ManageViews(string action, string[] viewNames) { if (viewNames.Length == 0) { return; } var viewNamesXml = GetViewNamesXml(viewNames); ExecuteGlobalSql(action, "pViewNames", viewNamesXml); } private void ManageStoredProcedures(string action, string[] storedProcedureNames) { if (storedProcedureNames.Length == 0) { return; } var storedProcedureNamesXml = GetStoredProcedureNamesXml(storedProcedureNames); ExecuteGlobalSql(action, "pStoredProcedureNames", storedProcedureNamesXml); } private void ManageFunctions(string action, string[] functionNames) { if (functionNames.Length == 0) { return; } var functionNamesXml = GetFunctionNamesXml(functionNames); ExecuteGlobalSql(action, "pFunctionNames", functionNamesXml); } private void ExecuteGlobalSql(string action, string parameterName, string parameterXml) { var sql = new StringBuilder(); sql.AppendLine($"DECLARE @{parameterName} XML = '{parameterXml}'"); sql.AppendLine($"EXEC [dbo].[sp_Global_{action}] NULL, @{parameterName}"); Execute.Sql(sql.ToString()); } private string GetViewNamesXml(string[] viewNames) { return GetXml("ViewNames", "ViewName", viewNames); } private string GetStoredProcedureNamesXml(string[] storedProcedureNames) { return GetXml("StoredProcedureNames", "StoredProcedureName", storedProcedureNames); } private string GetFunctionNamesXml(string[] functionNames) { return GetXml("FunctionNames", "FunctionName", functionNames); } private string GetXml(string rootNodeName, string childNodeName, string[] contents) { var root = new XElement(rootNodeName); foreach (string content in contents) { root.Add(new XElement(childNodeName, content)); } var xml = new XDocument(root); return xml.ToString(); } #endregion } }