private static void DoScript( string pathOrNull, bool naive, ConnectionStringSettings connectionStringSettings, DashingSettings dashingSettings, ReverseEngineerSettings reverseEngineerSettings) { DisplayMigrationHeader(naive, dashingSettings); // fetch the to state var config = (IConfiguration)configObject; IEnumerable <string> warnings, errors; var migrationScript = GenerateMigrationScript(connectionStringSettings, reverseEngineerSettings, config, naive, out warnings, out errors); // report errors DisplayMigrationWarningsAndErrors(errors, warnings); if (string.IsNullOrWhiteSpace(migrationScript)) { migrationScript = "-- Nothing to be migrated"; } // write it using (var writer = string.IsNullOrEmpty(pathOrNull) ? Console.Out : new StreamWriter(File.OpenWrite(pathOrNull))) { writer.WriteLine(migrationScript); } }
private static void DoSeed(ConnectionStringSettings connectionStringSettings) { // fetch the to state var config = (IConfiguration)configObject; var factory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName); using (var connection = factory.CreateConnection()) { if (connection == null) { throw new Exception("Could not connect to database"); } connection.ConnectionString = connectionStringSettings.ConnectionString; connection.Open(); // now let's call Seed var seederConfig = config as ISeeder; if (seederConfig != null) { using (new TimedOperation("-- Executing seeds")) { using (var session = config.BeginSession(connection)) { seederConfig.Seed(session); session.Complete(); } } } } }
private static object LoadConfiguration( Assembly configAssembly, DashingSettings dashingSettings, ConnectionStringSettings connectionStringSettings) { // fetch the to state var configType = configAssembly.GetLoadableTypes().SingleOrDefault(t => t.FullName == dashingSettings.ConfigurationName); if (configType == null) { using (Color(ConsoleColor.Red)) { var candidates = configAssembly.GetLoadableTypes().Where(t => t.GetInterface(typeof(IConfiguration).FullName) != null).ToArray(); if (candidates.Any()) { throw new CatchyException( "Could not locate {0}, but found candidates: {1}", dashingSettings.ConfigurationName, string.Join(", ", candidates.Select(c => c.FullName))); } throw new CatchyException("Could not locate {0}, and found no candidate configurations", dashingSettings.ConfigurationName); } } // attempt to find the call to ConfigurationManager and overwrite the connection string InjectConnectionString(dashingSettings, connectionStringSettings); // TODO add in a factory way of generating the config for cases where constructor not empty return(Activator.CreateInstance(configType)); }
private static void InjectConnectionString(DashingSettings dashingSettings, ConnectionStringSettings connectionStringSettings) { var assemblyDefinition = AssemblyDefinition.ReadAssembly(dashingSettings.PathToDll); var cecilConfigType = assemblyDefinition.MainModule.Types.Single(t => t.FullName == dashingSettings.ConfigurationName); var constructor = cecilConfigType.Methods.FirstOrDefault(m => m.IsConstructor && !m.HasParameters); // default constructor if (constructor == null) { using (Color(ConsoleColor.Red)) { throw new CatchyException("Unable to find a Default Constructor on the Configuration"); } } var getConnectionStringCall = constructor.Body.Instructions.FirstOrDefault( i => i.OpCode.Code == Code.Call && i.Operand.ToString() == "System.Configuration.ConnectionStringSettingsCollection System.Configuration.ConfigurationManager::get_ConnectionStrings()"); if (getConnectionStringCall == null) { using (Color(ConsoleColor.Red)) { throw new CatchyException("Unable to find the ConnectionStrings call in the constructor"); } } var connectionStringKey = getConnectionStringCall.Next.Operand.ToString(); // override readonly property of connectionstrings var readOnlyField = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); if (readOnlyField != null) { readOnlyField.SetValue(ConfigurationManager.ConnectionStrings, false); } // remove any existing if (ConfigurationManager.ConnectionStrings[connectionStringKey] != null) { ConfigurationManager.ConnectionStrings.Remove(connectionStringKey); } // and add in the one from our ini ConfigurationManager.ConnectionStrings.Add( new System.Configuration.ConnectionStringSettings( connectionStringKey, connectionStringSettings.ConnectionString, connectionStringSettings.ProviderName)); }
private static void DoReverseEngineer( CommandLineOptions options, DashingSettings dashingSettings, ReverseEngineerSettings reverseEngineerSettings, ConnectionStringSettings connectionString) { // overwrite the path with the default if necessary if (string.IsNullOrEmpty(options.Location)) { options.Location = dashingSettings.DefaultSavePath; } // if it is still empty, ... if (string.IsNullOrEmpty(options.Location) && options.ReverseEngineer) { throw new CatchyException("You must specify a location for generated files to be saved"); } // require a generated namespace if (string.IsNullOrEmpty(reverseEngineerSettings.GeneratedNamespace)) { throw new CatchyException("You must specify a GeneratedNamespace in the Project ini file"); } DatabaseSchema schema; var engineer = new Engineer(reverseEngineerSettings.ExtraPluralizationWords); var databaseReader = new DatabaseReader(connectionString.ConnectionString, connectionString.ProviderName); schema = databaseReader.ReadAll(); var maps = engineer.ReverseEngineer( schema, new DialectFactory().Create(connectionString.ToSystem()), reverseEngineerSettings.GetTablesToIgnore(), consoleAnswerProvider, true); var reverseEngineer = new ModelGenerator(); var sources = reverseEngineer.GenerateFiles(maps, schema, reverseEngineerSettings.GeneratedNamespace, consoleAnswerProvider); foreach (var source in sources) { File.WriteAllText(options.Location + "\\" + source.Key + ".cs", source.Value); } }
private static void ParseIni( CommandLineOptions options, out ConnectionStringSettings connectionStringSettings, out DashingSettings dashingSettings, out ReverseEngineerSettings reverseEngineerSettings) { var config = IniParser.Parse(options.ConfigPath); connectionStringSettings = new ConnectionStringSettings(); connectionStringSettings = IniParser.AssignTo(config["Database"], connectionStringSettings); dashingSettings = new DashingSettings(); dashingSettings = IniParser.AssignTo(config["Dashing"], dashingSettings); // fix path to dll to be avsolute path if (!Path.IsPathRooted(dashingSettings.PathToDll)) { dashingSettings.PathToDll = Path.Combine(Path.GetDirectoryName(options.ConfigPath), dashingSettings.PathToDll); } reverseEngineerSettings = new ReverseEngineerSettings(); reverseEngineerSettings = IniParser.AssignTo(config["ReverseEngineer"], reverseEngineerSettings); }
private static void CreateDatabaseIfNotExists(ConnectionStringSettings connectionStringSettings, DbProviderFactory factory, ISqlDialect dialect) { using (new TimedOperation("-- Checking for Existence of Database...")) { var connectionStringManipulator = new ConnectionStringManipulator(connectionStringSettings.ToSystem()); using (var connection = factory.CreateConnection()) { connection.ConnectionString = connectionStringManipulator.GetRootConnectionString().ConnectionString; connection.Open(); var databaseName = connectionStringManipulator.GetDatabaseName(); Trace("Looking for {0}", databaseName); if (!connection.Query(dialect.CheckDatabaseExists(databaseName)).Any()) { Trace("Not Found"); Trace("Creating"); connection.Execute(dialect.CreateDatabase(databaseName)); Trace("Created"); } else { Trace("Found!"); } } } }
private static string GenerateMigrationScript( ConnectionStringSettings connectionStringSettings, ReverseEngineerSettings reverseEngineerSettings, IConfiguration configuration, bool naive, out IEnumerable <string> warnings, out IEnumerable <string> errors) { // fetch the from state var dialectFactory = new DialectFactory(); var dialect = dialectFactory.Create(connectionStringSettings.ToSystem()); var factory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName); // create database if not exists CreateDatabaseIfNotExists(connectionStringSettings, factory, dialect); DatabaseSchema schema; using (new TimedOperation("-- Reading database contents...")) { var databaseReader = new DatabaseReader(connectionStringSettings.ConnectionString, connectionStringSettings.ProviderName); schema = databaseReader.ReadAll(); } IEnumerable <IMap> fromMaps; using (new TimedOperation("-- Reverse engineering...")) { Console.WriteLine(); var engineer = new Engineer(reverseEngineerSettings.ExtraPluralizationWords); fromMaps = engineer.ReverseEngineer(schema, dialect, reverseEngineerSettings.GetTablesToIgnore(), consoleAnswerProvider, false); Console.Write("-- "); } using (var connection = factory.CreateConnection()) { connection.ConnectionString = connectionStringSettings.ConnectionString; // set up migrator IMigrator migrator; if (naive) { throw new NotSupportedException("The Naive Migrator is no longer supported"); } migrator = new Migrator( dialect, new CreateTableWriter(dialect), new AlterTableWriter(dialect), new DropTableWriter(dialect), new StatisticsProvider(connection, dialect)); // run the migrator string script; using (new TimedOperation("-- Generating diff...")) { script = migrator.GenerateSqlDiff( fromMaps, configuration.Maps, consoleAnswerProvider, new ConsoleLogger(isVerbose), reverseEngineerSettings.GetIndexesToIgnore(), out warnings, out errors); // TODO: do things with warnings and errors return(script); } } }
private static void DoScript( string pathOrNull, bool naive, ConnectionStringSettings connectionStringSettings, DashingSettings dashingSettings, ReverseEngineerSettings reverseEngineerSettings) { DisplayMigrationHeader(naive, dashingSettings); // fetch the to state var config = (IConfiguration)configObject; IEnumerable<string> warnings, errors; var migrationScript = GenerateMigrationScript(connectionStringSettings, reverseEngineerSettings, config, naive, out warnings, out errors); // report errors DisplayMigrationWarningsAndErrors(errors, warnings); if (string.IsNullOrWhiteSpace(migrationScript)) { migrationScript = "-- Nothing to be migrated"; } // write it using (var writer = string.IsNullOrEmpty(pathOrNull) ? Console.Out : new StreamWriter(File.OpenWrite(pathOrNull))) { writer.WriteLine(migrationScript); } }
private static void DoMigrate( bool naive, ConnectionStringSettings connectionStringSettings, DashingSettings dashingSettings, ReverseEngineerSettings reverseEngineerSettings) { DisplayMigrationHeader(naive, dashingSettings); // fetch the to state var config = (IConfiguration)configObject; IEnumerable<string> warnings, errors; var script = GenerateMigrationScript(connectionStringSettings, reverseEngineerSettings, config, naive, out warnings, out errors); if (DisplayMigrationWarningsAndErrors(errors, warnings)) { using (Color(ConsoleColor.Red)) { Console.WriteLine("-- Fatal errors encountered: aborting migration. Please review the output."); } } else { // migrate it var factory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName); using (var connection = factory.CreateConnection()) { if (connection == null) { throw new Exception("Could not connect to database"); } connection.ConnectionString = connectionStringSettings.ConnectionString; connection.Open(); if (string.IsNullOrWhiteSpace(script)) { using (Color(ConsoleColor.Green)) { Console.WriteLine("-- No migration script to run"); } } else { using (new TimedOperation("-- Executing migration script on {0}", connection.ConnectionString)) { using (var command = connection.CreateCommand()) { using (Color(ConsoleColor.DarkGray)) { Console.WriteLine(); Console.WriteLine(script); Console.WriteLine(); } command.CommandText = script; command.ExecuteNonQuery(); } } } // now let's call Seed var seederConfig = config as ISeeder; if (seederConfig != null) { using (new TimedOperation("-- Executing seeds")) { using (var session = config.BeginSession(connection)) { seederConfig.Seed(session); session.Complete(); } } } } } }
private static void DoMigrate( bool naive, ConnectionStringSettings connectionStringSettings, DashingSettings dashingSettings, ReverseEngineerSettings reverseEngineerSettings) { DisplayMigrationHeader(naive, dashingSettings); // fetch the to state var config = (IConfiguration)configObject; IEnumerable <string> warnings, errors; var script = GenerateMigrationScript(connectionStringSettings, reverseEngineerSettings, config, naive, out warnings, out errors); if (DisplayMigrationWarningsAndErrors(errors, warnings)) { using (Color(ConsoleColor.Red)) { Console.WriteLine("-- Fatal errors encountered: aborting migration. Please review the output."); } } else { // migrate it var factory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName); using (var connection = factory.CreateConnection()) { if (connection == null) { throw new Exception("Could not connect to database"); } connection.ConnectionString = connectionStringSettings.ConnectionString; connection.Open(); if (string.IsNullOrWhiteSpace(script)) { using (Color(ConsoleColor.Green)) { Console.WriteLine("-- No migration script to run"); } } else { using (new TimedOperation("-- Executing migration script on {0}", connection.ConnectionString)) { using (var command = connection.CreateCommand()) { using (Color(ConsoleColor.DarkGray)) { Console.WriteLine(); Console.WriteLine(script); Console.WriteLine(); } command.CommandText = script; command.ExecuteNonQuery(); } } } // now let's call Seed var seederConfig = config as ISeeder; if (seederConfig != null) { using (new TimedOperation("-- Executing seeds")) { using (var session = config.BeginSession(connection)) { seederConfig.Seed(session); session.Complete(); } } } } } }
private static object LoadConfiguration( Assembly configAssembly, DashingSettings dashingSettings, ConnectionStringSettings connectionStringSettings) { // fetch the to state var configType = configAssembly.GetLoadableTypes().SingleOrDefault(t => t.FullName == dashingSettings.ConfigurationName); if (configType == null) { using (Color(ConsoleColor.Red)) { var candidates = configAssembly.GetLoadableTypes().Where(t => t.GetInterface(typeof(IConfiguration).FullName) != null).ToArray(); if (candidates.Any()) { throw new CatchyException( "Could not locate {0}, but found candidates: {1}", dashingSettings.ConfigurationName, string.Join(", ", candidates.Select(c => c.FullName))); } throw new CatchyException("Could not locate {0}, and found no candidate configurations", dashingSettings.ConfigurationName); } } // attempt to find the call to ConfigurationManager and overwrite the connection string InjectConnectionString(dashingSettings, connectionStringSettings); // TODO add in a factory way of generating the config for cases where constructor not empty return Activator.CreateInstance(configType); }
private static string GenerateMigrationScript( ConnectionStringSettings connectionStringSettings, ReverseEngineerSettings reverseEngineerSettings, IConfiguration configuration, bool naive, out IEnumerable<string> warnings, out IEnumerable<string> errors) { // fetch the from state var dialectFactory = new DialectFactory(); var dialect = dialectFactory.Create(connectionStringSettings.ToSystem()); var factory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName); // create database if not exists CreateDatabaseIfNotExists(connectionStringSettings, factory, dialect); DatabaseSchema schema; using (new TimedOperation("-- Reading database contents...")) { var databaseReader = new DatabaseReader(connectionStringSettings.ConnectionString, connectionStringSettings.ProviderName); schema = databaseReader.ReadAll(); } IEnumerable<IMap> fromMaps; using (new TimedOperation("-- Reverse engineering...")) { Console.WriteLine(); var engineer = new Engineer(reverseEngineerSettings.ExtraPluralizationWords); fromMaps = engineer.ReverseEngineer(schema, dialect, reverseEngineerSettings.GetTablesToIgnore(), consoleAnswerProvider, false); Console.Write("-- "); } using (var connection = factory.CreateConnection()) { connection.ConnectionString = connectionStringSettings.ConnectionString; // set up migrator IMigrator migrator; if (naive) { throw new NotSupportedException("The Naive Migrator is no longer supported"); } migrator = new Migrator( dialect, new CreateTableWriter(dialect), new AlterTableWriter(dialect), new DropTableWriter(dialect), new StatisticsProvider(connection, dialect)); // run the migrator string script; using (new TimedOperation("-- Generating diff...")) { script = migrator.GenerateSqlDiff( fromMaps, configuration.Maps, consoleAnswerProvider, new ConsoleLogger(isVerbose), reverseEngineerSettings.GetIndexesToIgnore(), out warnings, out errors); // TODO: do things with warnings and errors return script; } } }