/// <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);
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        /// <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());
        }
Esempio n. 7
0
        /// <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);
        }
Esempio n. 9
0
        /// <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()));
        }