/// <summary> /// Tries to find configuration Type. /// If none or multiple found NULL will be returned. /// </summary> /// <param name="projectPath"></param> /// <param name="repoType"></param> /// <param name="multipleFound"></param> /// <returns></returns> internal static Type FindSingleConfiguration(string projectPath, Type repoType, out bool multipleFound) { multipleFound = false; var loadedProject = new ProjectEvalutionHelper().LoadEvalutionProject(projectPath); var baseType = typeof(RepoMigrationConfigurationBase <>).MakeGenericType(repoType); var configTypes = loadedProject .GetTypes() .Where(baseType.IsAssignableFrom) .ToArray(); //if none found then we will end up creating one. if (!configTypes.Any()) { return(null); } if (configTypes.Length == 1) { return(configTypes.Single()); } multipleFound = true; return(null); }
/// <summary> /// Applies all migrations for the given repository. /// </summary> /// <param name="criteria"></param> public void ApplyMigrations(ApplyMigrationCriteria criteria) { var configurationStatus = GetMigrationConfigurationStatus(criteria.ProjectPath, criteria.RepoName); if (!configurationStatus.Enabled) { LoggerBase.Log("Migrations are not enabled, can not apply any migrations."); return; } if (configurationStatus.MigrationType != MigrationToUse.Manual) { LoggerBase.Log("Manual Migrations are not enabled, can not apply any migrations."); return; } var repoInfo = TypeHandler.FindSingleRepo(criteria.ProjectPath, criteria.RepoName); //if null we need to drop out. if (repoInfo == null) { return; } AssertRepoHasEmptyConstructor(repoInfo.RepoType); EnsureDbAndMigrationTableExists(criteria.ProjectPath, repoInfo.RepoType, criteria.ConfigFilePath); var runner = new MigrationRunner(); runner.ApplyMigrations(criteria); //clean up ProjectEvalutionHelper.FinishedWithProject(criteria.ProjectPath); }
/// <summary> /// Automatically update the database schema to bring it up to date. /// </summary> /// <param name="criteria">creation criteria</param> public void UpdateDatabaseAutomatically(AutomaticUpdateCriteria criteria) { var configurationStatus = GetMigrationConfigurationStatus(criteria.ProjectFilePath, criteria.RepoName); if (!configurationStatus.Enabled) { LoggerBase.Log("Migrations are not enabled, can not apply any migrations."); return; } if (configurationStatus.MigrationType != MigrationToUse.Automatic) { LoggerBase.Log("automatic Migrations are not enabled, can not apply any migrations."); return; } var repoInfo = TypeHandler.FindSingleRepo(criteria.ProjectFilePath, criteria.RepoName); //if null we need to drop out. if (repoInfo == null) { return; } AssertRepoHasEmptyConstructor(repoInfo.RepoType); EnsureDbAndMigrationTableExists(criteria.ProjectFilePath, repoInfo.RepoType, criteria.ConfigFilePath); var updater = CreateSchemaUpdater(repoInfo.Assembly.Location, repoInfo.RepoType, criteria.ConfigFilePath); updater.Execute(true, true); //clean up ProjectEvalutionHelper.FinishedWithProject(criteria.ProjectFilePath); }
internal string CreateConfigurationFile(string projectPath, string repoName, string migrationFolder, MigrationToUse migrationType) { var projectNamespace = new ProjectEvalutionHelper().RootNameSpace(projectPath); var className = repoName + "Configuration"; var migrationFolderLocation = GetMigrationFolderLocation(projectPath, migrationFolder); if (!Directory.Exists(migrationFolderLocation)) { Directory.CreateDirectory(migrationFolderLocation); } var fileBuilder = new StringBuilder(); fileBuilder.AppendLine("using NHibernateRepo.Configuration;"); fileBuilder.AppendLine("using NHibernateRepo.Migrations;"); fileBuilder.AppendLine(""); fileBuilder.AppendLine(string.Format("namespace {0}.{1}", projectNamespace, migrationFolder)); fileBuilder.AppendLine("{"); fileBuilder.AppendLine(" public class " + className + " : RepoMigrationConfigurationBase<" + repoName + ">"); fileBuilder.AppendLine(" {"); fileBuilder.AppendLine(" public " + repoName + "Configuration()"); fileBuilder.AppendLine(" {"); fileBuilder.AppendLine(" Enabled = true;"); fileBuilder.AppendLine(" MigrationType = MigrationToUse." + migrationType + ";"); fileBuilder.AppendLine(" RootMigrationFolder = @\"Migrations\\" + repoName + "Migrations\";"); fileBuilder.AppendLine(" }"); fileBuilder.AppendLine(" }"); fileBuilder.AppendLine("}"); var path = Path.Combine(CreateFileLocationPath(projectPath, className, migrationFolder)); File.WriteAllText(path, fileBuilder.ToString()); return(path); }
/// <summary> /// Creates a CS file that inherits from BaseMigration that will execute the SQL schema changes. /// </summary> /// <param name="criteria">description of what to do and where to put the file</param> public void CreateScript(CreationCriteria criteria) { var configurationStatus = GetMigrationConfigurationStatus(criteria.ProjectFileLocation, criteria.RepoName); if (!configurationStatus.Enabled) { LoggerBase.Log("Migrations are not enabled, can not create any migrations."); return; } if (configurationStatus.MigrationType != MigrationToUse.Manual) { LoggerBase.Log("Manual Migrations are not enabled, can not create manual migrations."); return; } var repoInfo = TypeHandler.FindSingleRepo(criteria.ProjectFileLocation, criteria.RepoName); //if null we need to drop out. if (repoInfo == null) { LoggerBase.Log("Unable to find repo"); return; } AssertRepoHasEmptyConstructor(repoInfo.RepoType); EnsureDbAndMigrationTableExists(criteria.ProjectFileLocation, repoInfo.RepoType, criteria.ConfigFilePath); //ensure that we have the case correct. criteria.RepoName = repoInfo.RepoType.Name; var configuration = TypeHandler.FindConfiguration(criteria.ProjectFileLocation, repoInfo.RepoType); //if null something bad happend, drop out if (configuration == null) { LoggerBase.Log("unable to find configuration file"); return; } var updater = CreateSchemaUpdater(repoInfo.Assembly.Location, repoInfo.RepoType, criteria.ConfigFilePath); var fileMigrationHandler = new MigrationFileHandler(updater); var projectFileHandler = new ProjectDteHelper(); //set the mgiration folder form config: criteria.MigrationPath = configuration.RootMigrationFolder; var filePath = fileMigrationHandler.CreateFile(criteria); projectFileHandler.AddFile(criteria.ProjectFileLocation, configuration.RootMigrationFolder, filePath, showFile: true); LoggerBase.Log("Created migration file."); //clean up ProjectEvalutionHelper.FinishedWithProject(criteria.ProjectFileLocation); }
/// <summary> /// Finds all migration Types / Classes from the given project. /// </summary> /// <param name="projectPath"></param> /// <param name="repoType"></param> /// <returns></returns> internal static Type[] FindAllMigrations(string projectPath, Type repoType) { var loadedProject = new ProjectEvalutionHelper().LoadEvalutionProject(projectPath); var baseType = typeof(BaseMigration <>).MakeGenericType(repoType); return(loadedProject .GetTypes() .Where(baseType.IsAssignableFrom) .ToArray()); }
/// <summary> /// Enables the ability for that project to be able to use NHibernate Repo migrations, automatic or manual. /// </summary> public void EnableMigrations(EnableMigrationsCriteria criteria) { MessageFilter.Register(); var repoInfo = TypeHandler.FindSingleRepo(criteria.ProjectPath, criteria.RepoName); //if it is null something is wrong so drop out. if (repoInfo == null) { return; } AssertRepoHasEmptyConstructor(repoInfo.RepoType); EnsureDbAndMigrationTableExists(criteria.ProjectPath, repoInfo.RepoType, criteria.ConfigFilePath); var repoBase = TypeHandler.CreateRepoBase(repoInfo.Assembly.Location, repoInfo.RepoType); //create migration log table, if it doesn't exist. var updater = CreateSchemaUpdater(criteria.ProjectPath, typeof(MigrationRepo), criteria.ConfigFilePath, repoBase.ConnectionStringOrName); updater.Execute(true, true); bool multipleFound = false; var configType = TypeHandler.FindSingleConfiguration(criteria.ProjectPath, repoInfo.RepoType, out multipleFound); //this should not happen. should only ever have one config per repo type. if (multipleFound) { return; } if (configType == null) { LoggerBase.Log("Adding migration configuration"); var filePath = new ConfigurationFileHandler().CreateConfigurationFile(criteria.ProjectPath, repoInfo.RepoType.Name, "Migrations", MigrationToUse.Manual); new ProjectDteHelper().AddFile(criteria.ProjectPath, "Migrations", filePath, showFile: true); } else { LoggerBase.Log("System is already configured for migrations, see class: " + configType.Name); } //clean up ProjectEvalutionHelper.FinishedWithProject(criteria.ProjectPath); MessageFilter.Revoke(); }
public string CreateFile(CreationCriteria criteria) { var projectNamespace = new ProjectEvalutionHelper().RootNameSpace(criteria.ProjectFileLocation); var migrationFileInfo = GenerateFileLocation(criteria); if (!Directory.Exists(migrationFileInfo.Folder)) { Directory.CreateDirectory(migrationFileInfo.Folder); } //if it already exists delete it.. it should not at this point. this is a just incase. if (File.Exists(migrationFileInfo.FullFilePath)) { File.Delete(migrationFileInfo.FullFilePath); } _schemaUpdater.Execute(_logScript, false); var fileBuilder = new StringBuilder(); fileBuilder.AppendLine("using NHibernateRepo.Migrations;"); fileBuilder.AppendLine("using System;"); fileBuilder.AppendLine(""); fileBuilder.AppendLine(string.Format("namespace {0}.{1}", projectNamespace, criteria.MigrationPath.Replace("\\", ".").Replace("-", "."))); fileBuilder.AppendLine("{"); fileBuilder.AppendLine(" public class " + migrationFileInfo.ClassName + " : BaseMigration<" + criteria.RepoName + ">"); fileBuilder.AppendLine(" {"); fileBuilder.AppendLine(" public override void Execute()"); fileBuilder.AppendLine(" {"); foreach (var script in Scripts) { fileBuilder.AppendLine(" "); fileBuilder.AppendLine(" ExecuteSql(@\"" + script + "\");"); } fileBuilder.AppendLine(" "); fileBuilder.AppendLine(" }"); fileBuilder.AppendLine(" }"); fileBuilder.AppendLine("}"); File.WriteAllText(migrationFileInfo.FullFilePath, fileBuilder.ToString()); return(migrationFileInfo.FullFilePath); }
/// <summary> /// Applies the database update, be that automatic or manual according to the configuration class. /// </summary> /// <param name="criteria"></param> public void UpdateDatabase(UpdateDatabaseCriteria criteria) { var status = GetMigrationConfigurationStatus(criteria.ProjectFilePath, criteria.RepoName); if (!status.Enabled) { LoggerBase.Log("Migrations are not enabled"); return; } switch (status.MigrationType) { case MigrationToUse.Automatic: UpdateDatabaseAutomatically(new AutomaticUpdateCriteria { ProjectFilePath = criteria.ProjectFilePath, RepoName = criteria.RepoName }); break; case MigrationToUse.Manual: ApplyMigrations(new ApplyMigrationCriteria { ProjectPath = criteria.ProjectFilePath, RepoName = criteria.RepoName }); break; default: throw new ArgumentOutOfRangeException(); } //clean up ProjectEvalutionHelper.FinishedWithProject(criteria.ProjectFilePath); }
/// <summary> /// Tries to find the implementation of the base repo object from the given project. /// Will return NULL if more than one is found. The name can be passed in if the repo name is known, (required if multiple repos in same project). /// </summary> /// <param name="projectPath"></param> /// <param name="optionalRepoName"></param> /// <returns></returns> internal static RepoSearchResult FindSingleRepo(string projectPath, string optionalRepoName) { LoggerBase.Log(string.Format("Starting to find single Repo: '{0}, {1}", optionalRepoName, projectPath), isDebugMessage: true); var loadedProject = new ProjectEvalutionHelper().LoadEvalutionProject(projectPath); LoggerBase.Log("LoadedProject: " + loadedProject.FullName, isDebugMessage: true); var repoTypes = new Type[0]; try { repoTypes = loadedProject .GetTypes() .Where(t => t.IsSubclassOf(typeof(BaseRepo)) && !t.IsGenericType ) .ToArray(); } catch (ReflectionTypeLoadException ex) { LoggerBase.Log("Error whilst getting all classes that inherit from baserepo within loadedproject"); Exception[] loaderExceptions = ex.LoaderExceptions; LoggerBase.Log("Logger exceptions:", isDebugMessage: true); foreach (var exception in loaderExceptions) { LoggerBase.Log(exception, isDebugMessage: true); } LoggerBase.Log(ex, isDebugMessage: true); throw; } if (!string.IsNullOrWhiteSpace(optionalRepoName)) { var repos = repoTypes.Where(r => r.Name.Equals(optionalRepoName, StringComparison.InvariantCultureIgnoreCase)).ToArray(); if (!repos.Any()) { LoggerBase.Log("No repo class found with name: " + optionalRepoName); return(null); } if (repos.Count() > 1) { LoggerBase.Log("More than one repo with same name found, please ensure repo is uniquely named in repo project."); return(null); } return(new RepoSearchResult(loadedProject, repos.Single())); } if (!repoTypes.Any()) { LoggerBase.Log("No repo class found"); return(null); } if (repoTypes.Count() > 1) { LoggerBase.Log("More than one repo found, please specify which repo to use."); return(null); } return(new RepoSearchResult(loadedProject, repoTypes.Single())); }