protected virtual void Generate([NotNull] MigrationOperation operation, [NotNull] IndentedStringBuilder builder) { Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); throw new InvalidOperationException(ToolsCoreStrings.UnknownOperation(operation.GetType())); }
protected virtual string GetDirectory( [NotNull] string projectDir, [CanBeNull] string siblingFileName, [NotNull] string subnamespace) { Check.NotEmpty(projectDir, nameof(projectDir)); Check.NotNull(subnamespace, nameof(subnamespace)); var defaultDirectory = Path.Combine(projectDir, Path.Combine(subnamespace.Split('.'))); if (siblingFileName != null) { var siblingPath = TryGetProjectFile(projectDir, siblingFileName); if (siblingPath != null) { var lastDirectory = Path.GetDirectoryName(siblingPath); if (!defaultDirectory.Equals(lastDirectory, StringComparison.OrdinalIgnoreCase)) { _logger.Value.LogDebug(ToolsCoreStrings.ReusingDirectory(siblingFileName)); return(lastDirectory); } } } return(defaultDirectory); }
public virtual MigrationFiles Save([NotNull] string projectDir, [NotNull] ScaffoldedMigration migration) { Check.NotEmpty(projectDir, nameof(projectDir)); Check.NotNull(migration, nameof(migration)); var lastMigrationFileName = migration.PreviousMigrationId + migration.FileExtension; var migrationDirectory = GetDirectory(projectDir, lastMigrationFileName, migration.MigrationSubNamespace); var migrationFile = Path.Combine(migrationDirectory, migration.MigrationId + migration.FileExtension); var migrationMetadataFile = Path.Combine(migrationDirectory, migration.MigrationId + ".Designer" + migration.FileExtension); var modelSnapshotFileName = migration.SnapshotName + migration.FileExtension; var modelSnapshotDirectory = GetDirectory(projectDir, modelSnapshotFileName, migration.SnapshotSubnamespace); var modelSnapshotFile = Path.Combine(modelSnapshotDirectory, modelSnapshotFileName); _logger.Value.LogDebug(ToolsCoreStrings.WritingMigration(migrationFile)); Directory.CreateDirectory(migrationDirectory); File.WriteAllText(migrationFile, migration.MigrationCode, Encoding.UTF8); File.WriteAllText(migrationMetadataFile, migration.MetadataCode, Encoding.UTF8); _logger.Value.LogDebug(ToolsCoreStrings.WritingSnapshot(modelSnapshotFile)); Directory.CreateDirectory(modelSnapshotDirectory); File.WriteAllText(modelSnapshotFile, migration.SnapshotCode, Encoding.UTF8); return(new MigrationFiles { MigrationFile = migrationFile, MetadataFile = migrationMetadataFile, SnapshotFile = modelSnapshotFile }); }
public virtual string UnknownLiteral([CanBeNull] object value) { if (value == null) { return("null"); } var type = value.GetType().UnwrapNullableType(); Func <CSharpHelper, object, string> literalFunc; if (_literalFuncs.TryGetValue(type, out literalFunc)) { return(literalFunc(this, value)); } var enumValue = value as Enum; if (enumValue != null) { return(Literal(enumValue)); } throw new InvalidOperationException(ToolsCoreStrings.UnknownLiteral(value.GetType())); }
public void UnknownLiteral_throws_when_unknown() { var ex = Assert.Throws <InvalidOperationException>( () => new CSharpHelper().UnknownLiteral(new object())); Assert.Equal(ToolsCoreStrings.UnknownLiteral(typeof(object)), ex.Message); }
public virtual void CheckValidity() { if (string.IsNullOrEmpty(ConnectionString)) { throw new ArgumentException(ToolsCoreStrings.ConnectionStringRequired); } if (string.IsNullOrEmpty(ProjectPath)) { throw new ArgumentException(ToolsCoreStrings.ProjectPathRequired); } if (!string.IsNullOrWhiteSpace(ContextClassName) && (!CSharpUtilities.Instance.IsValidIdentifier(ContextClassName) || CSharpUtilities.Instance.IsCSharpKeyword(ContextClassName))) { throw new ArgumentException( ToolsCoreStrings.ContextClassNotValidCSharpIdentifier(ContextClassName)); } if (string.IsNullOrEmpty(ProjectRootNamespace)) { throw new ArgumentException(ToolsCoreStrings.RootNamespaceRequired); } }
public void Throws_for_no_parameterless_constructor() { using (var directory = new TempDirectory()) { var targetDir = directory.Path; var source = new BuildSource { TargetDir = targetDir, References = { BuildReference.ByName("System.Diagnostics.DiagnosticSource", copyLocal: true), BuildReference.ByName("System.Interactive.Async", copyLocal: true), BuildReference.ByName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), BuildReference.ByName("Microsoft.AspNetCore.Hosting.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools.Core", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational.Design", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Caching.Memory", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Configuration.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.FileProviders.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Logging", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Options", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.PlatformAbstractions", copyLocal: true), BuildReference.ByName("Remotion.Linq", copyLocal: true) }, Sources = { @" using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; namespace MyProject { internal class MyContext : DbContext { public MyContext(DbContextOptions<MyContext> options) :base(options) {} } }" } }; var build = source.Build(); using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) { var ex = Assert.Throws <OperationException>( () => executor.GetMigrations("MyContext")); Assert.Equal( ToolsCoreStrings.NoParameterlessConstructor("MyContext"), ex.Message); } } }
private Type GetProviderDesignTimeServices(string provider, bool throwOnError) { Assembly providerAssembly; try { providerAssembly = _assemblyLoader.Load(provider); } catch (Exception ex) { if (!throwOnError) { return(null); } throw new OperationException(ToolsCoreStrings.CannotFindRuntimeProviderAssembly(provider), ex); } var providerServicesAttribute = providerAssembly.GetCustomAttribute <DesignTimeProviderServicesAttribute>(); if (providerServicesAttribute == null) { if (!throwOnError) { return(null); } throw new InvalidOperationException( ToolsCoreStrings.CannotFindDesignTimeProviderAssemblyAttribute( nameof(DesignTimeProviderServicesAttribute), provider)); } Assembly designTimeProviderAssembly; try { designTimeProviderAssembly = _assemblyLoader.Load(providerServicesAttribute.AssemblyName); } catch (Exception ex) when(ex is FileNotFoundException || ex is FileLoadException || ex is BadImageFormatException) { if (!throwOnError) { return(null); } throw new OperationException( ToolsCoreStrings.CannotFindDesignTimeProviderAssembly(providerServicesAttribute.PackageName), ex); } return(designTimeProviderAssembly.GetType( providerServicesAttribute.TypeName, throwOnError: true, ignoreCase: false)); }
private DbContext CreateContext(Func <DbContext> factory) { var context = factory(); _logger.Value.LogDebug(ToolsCoreStrings.LogUseContext(context.GetType().Name)); var loggerFactory = context.GetService <ILoggerFactory>(); loggerFactory.AddProvider(_loggerProvider); return(context); }
private KeyValuePair <Type, Func <DbContext> > FindContextType(string name) { var types = FindContextTypes(); if (string.IsNullOrEmpty(name)) { if (types.Count == 0) { throw new OperationException(ToolsCoreStrings.NoContext); } if (types.Count == 1) { return(types.First()); } throw new OperationException(ToolsCoreStrings.MultipleContexts); } var candidates = FilterTypes(types, name, ignoreCase: true); if (candidates.Count == 0) { throw new OperationException(ToolsCoreStrings.NoContextWithName(name)); } if (candidates.Count == 1) { return(candidates.First()); } // Disambiguate using case candidates = FilterTypes(candidates, name); if (candidates.Count == 0) { throw new OperationException(ToolsCoreStrings.MultipleContextsWithName(name)); } if (candidates.Count == 1) { return(candidates.First()); } // Allow selecting types in the default namespace candidates = candidates.Where(t => t.Key.Namespace == null).ToDictionary(t => t.Key, t => t.Value); if (candidates.Count == 0) { throw new OperationException(ToolsCoreStrings.MultipleContextsWithQualifiedName(name)); } Debug.Assert(candidates.Count == 1, "candidates.Count is not 1."); return(candidates.First()); }
public void Throws_exceptions_for_incorrect_configuration() { var configuration = new ReverseEngineeringConfiguration { ConnectionString = null, ProjectPath = null, OutputPath = null }; Assert.Equal(ToolsCoreStrings.ConnectionStringRequired, Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ConnectionString = "NonEmptyConnectionString"; Assert.Equal(ToolsCoreStrings.ProjectPathRequired, Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ProjectPath = "NonEmptyProjectPath"; Assert.Equal(ToolsCoreStrings.RootNamespaceRequired, Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ContextClassName = @"Invalid!CSharp*Class&Name"; Assert.Equal(ToolsCoreStrings.ContextClassNotValidCSharpIdentifier(@"Invalid!CSharp*Class&Name"), Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ContextClassName = "1CSharpClassNameCannotStartWithNumber"; Assert.Equal(ToolsCoreStrings.ContextClassNotValidCSharpIdentifier("1CSharpClassNameCannotStartWithNumber"), Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ContextClassName = "volatile"; // cannot be C# keyword Assert.Equal(ToolsCoreStrings.ContextClassNotValidCSharpIdentifier("volatile"), Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.ContextClassName = "GoodClassName"; configuration.OutputPath = @"\AnAbsolutePath"; Assert.Equal(ToolsCoreStrings.RootNamespaceRequired, Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); configuration.OutputPath = @"A\Relative\Path"; Assert.Equal(ToolsCoreStrings.RootNamespaceRequired, Assert.Throws <ArgumentException>( () => configuration.CheckValidity()).Message); }
protected virtual string GetNamespace([CanBeNull] Type siblingType, [NotNull] string defaultNamespace) { if (siblingType != null) { var lastNamespace = siblingType.Namespace; if (lastNamespace != defaultNamespace) { _logger.Value.LogDebug(ToolsCoreStrings.ReusingNamespace(siblingType.Name)); return(lastNamespace); } } return(defaultNamespace); }
private void EnsureServices(IServiceProvider services) { var providerServices = services.GetRequiredService <IDatabaseProviderServices>(); if (!(providerServices is IRelationalDatabaseProviderServices)) { throw new OperationException(ToolsCoreStrings.NonRelationalProvider(providerServices.InvariantName)); } var assemblyName = _assembly.GetName(); var options = services.GetRequiredService <IDbContextOptions>(); var contextType = services.GetRequiredService <ICurrentDbContext>().Context.GetType(); var migrationsAssemblyName = RelationalOptionsExtension.Extract(options).MigrationsAssembly ?? contextType.GetTypeInfo().Assembly.GetName().Name; if (assemblyName.Name != migrationsAssemblyName && assemblyName.FullName != migrationsAssemblyName) { throw new OperationException( ToolsCoreStrings.MigrationsAssemblyMismatch(assemblyName.Name, migrationsAssemblyName)); } }
public virtual ScaffoldedMigration ScaffoldMigration( [NotNull] string migrationName, [NotNull] string rootNamespace, [CanBeNull] string subNamespace = null) { Check.NotEmpty(migrationName, nameof(migrationName)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); if (_migrationsAssembly.FindMigrationId(migrationName) != null) { throw new InvalidOperationException(ToolsCoreStrings.DuplicateMigrationName(migrationName)); } var subNamespaceDefaulted = false; if (string.IsNullOrEmpty(subNamespace)) { subNamespaceDefaulted = true; subNamespace = "Migrations"; } var lastMigration = _migrationsAssembly.Migrations.LastOrDefault(); var migrationNamespace = rootNamespace + "." + subNamespace; if (subNamespaceDefaulted) { migrationNamespace = GetNamespace(lastMigration.Value?.AsType(), migrationNamespace); } var sanitizedContextName = _contextType.Name; var genericMarkIndex = sanitizedContextName.IndexOf('`'); if (genericMarkIndex != -1) { sanitizedContextName = sanitizedContextName.Substring(0, genericMarkIndex); } if (ContainsForeignMigrations(migrationNamespace)) { if (subNamespaceDefaulted) { var builder = new StringBuilder() .Append(rootNamespace) .Append(".Migrations."); if (sanitizedContextName.EndsWith("Context", StringComparison.Ordinal)) { builder.Append(sanitizedContextName.Substring(0, sanitizedContextName.Length - 7)); } else { builder .Append(sanitizedContextName) .Append("Migrations"); } migrationNamespace = builder.ToString(); } else { _logger.Value.LogWarning(ToolsCoreStrings.ForeignMigrations(migrationNamespace)); } } var modelSnapshot = _migrationsAssembly.ModelSnapshot; var lastModel = modelSnapshot?.Model; var upOperations = _modelDiffer.GetDifferences(lastModel, _model); var downOperations = upOperations.Any() ? _modelDiffer.GetDifferences(_model, lastModel) : new List <MigrationOperation>(); var migrationId = _idGenerator.GenerateId(migrationName); var modelSnapshotNamespace = GetNamespace(modelSnapshot?.GetType(), migrationNamespace); var modelSnapshotName = sanitizedContextName + "ModelSnapshot"; if (modelSnapshot != null) { var lastModelSnapshotName = modelSnapshot.GetType().Name; if (lastModelSnapshotName != modelSnapshotName) { _logger.Value.LogDebug(ToolsCoreStrings.ReusingSnapshotName(lastModelSnapshotName)); modelSnapshotName = lastModelSnapshotName; } } if (upOperations.Any(o => o.IsDestructiveChange)) { _logger.Value.LogWarning(ToolsCoreStrings.DestructiveOperation); } var migrationCode = _migrationCodeGenerator.GenerateMigration( migrationNamespace, migrationName, upOperations, downOperations); var migrationMetadataCode = _migrationCodeGenerator.GenerateMetadata( migrationNamespace, _contextType, migrationName, migrationId, _model); var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, _model); return(new ScaffoldedMigration( _migrationCodeGenerator.FileExtension, lastMigration.Key, migrationCode, migrationId, migrationMetadataCode, GetSubNamespace(rootNamespace, migrationNamespace), modelSnapshotCode, modelSnapshotName, GetSubNamespace(rootNamespace, modelSnapshotNamespace))); }
private IDictionary <Type, Func <DbContext> > FindContextTypes() { _logger.Value.LogDebug(ToolsCoreStrings.LogFindingContexts); var contexts = new Dictionary <Type, Func <DbContext> >(); // Look for IDbContextFactory implementations var contextFactories = _startupAssembly.GetConstructibleTypes() .Where(t => typeof(IDbContextFactory <DbContext>).GetTypeInfo().IsAssignableFrom(t)); foreach (var factory in contextFactories) { var manufacturedContexts = from i in factory.ImplementedInterfaces where i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition() == typeof(IDbContextFactory <>) select i.GenericTypeArguments[0]; foreach (var context in manufacturedContexts) { contexts.Add( context, () => ((IDbContextFactory <DbContext>)Activator.CreateInstance(factory.AsType())).Create()); } } // Look for DbContext classes registered in the service provider var registeredContexts = _runtimeServices.GetServices <DbContextOptions>() .Select(o => o.ContextType); foreach (var context in registeredContexts.Where(c => !contexts.ContainsKey(c))) { contexts.Add( context, FindContextFactory(context) ?? (() => (DbContext)_runtimeServices.GetRequiredService(context))); } // Look for DbContext classes in assemblies var types = _startupAssembly.GetConstructibleTypes() .Concat(_assembly.GetConstructibleTypes()) .Select(i => i.AsType()); var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t)) .Concat( types.Where(t => typeof(Migration).IsAssignableFrom(t)) .Select(t => t.GetTypeInfo().GetCustomAttribute <DbContextAttribute>()?.ContextType) .Where(t => t != null)) .Distinct(); foreach (var context in contextTypes.Where(c => !contexts.ContainsKey(c))) { contexts.Add( context, FindContextFactory(context) ?? (Func <DbContext>)(() => { try { return((DbContext)Activator.CreateInstance(context)); } catch (MissingMethodException ex) { throw new OperationException(ToolsCoreStrings.NoParameterlessConstructor(context.Name), ex); } })); } return(contexts); }
public OperationExecutor([NotNull] object logHandler, [NotNull] IDictionary args, [NotNull] AssemblyLoader assemblyLoader) { Check.NotNull(logHandler, nameof(logHandler)); Check.NotNull(args, nameof(args)); Check.NotNull(assemblyLoader, nameof(assemblyLoader)); var unwrappedLogHandler = ForwardingProxy.Unwrap <IOperationLogHandler>(logHandler); var loggerProvider = new LoggerProvider(name => new CommandLoggerAdapter(name, unwrappedLogHandler)); var targetName = (string)args["targetName"]; var startupTargetName = (string)args["startupTargetName"]; var environment = (string)args["environment"]; _projectDir = (string)args["projectDir"]; var startupProjectDir = (string)args["startupProjectDir"]; var rootNamespace = (string)args["rootNamespace"]; // NOTE: LazyRef is used so any exceptions get passed to the resultHandler var startupAssembly = new LazyRef <Assembly>( () => assemblyLoader.Load(startupTargetName)); var assembly = new LazyRef <Assembly>( () => { try { return(assemblyLoader.Load(targetName)); } catch (Exception ex) { throw new OperationException( ToolsCoreStrings.UnreferencedAssembly(targetName, startupTargetName), ex); } }); _contextOperations = new LazyRef <DbContextOperations>( () => new DbContextOperations( loggerProvider, assembly.Value, startupAssembly.Value, environment, startupProjectDir)); _databaseOperations = new LazyRef <DatabaseOperations>( () => new DatabaseOperations( loggerProvider, assemblyLoader, startupAssembly.Value, environment, _projectDir, startupProjectDir, rootNamespace)); _migrationsOperations = new LazyRef <MigrationsOperations>( () => new MigrationsOperations( loggerProvider, assembly.Value, assemblyLoader, startupAssembly.Value, environment, _projectDir, startupProjectDir, rootNamespace)); }
public void GetMigrations_throws_when_target_and_migrations_assemblies_mismatch() { using (var directory = new TempDirectory()) { var targetDir = directory.Path; var source = new BuildSource { TargetDir = targetDir, References = { BuildReference.ByName("System.Diagnostics.DiagnosticSource", copyLocal: true), BuildReference.ByName("System.Interactive.Async", copyLocal: true), BuildReference.ByName("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"), BuildReference.ByName("Microsoft.AspNetCore.Hosting.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Tools.Core", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.Relational.Design", copyLocal: true), BuildReference.ByName("Microsoft.EntityFrameworkCore.SqlServer", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Caching.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Caching.Memory", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Configuration.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.DependencyInjection.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.FileProviders.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Logging", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Logging.Abstractions", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.Options", copyLocal: true), BuildReference.ByName("Microsoft.Extensions.PlatformAbstractions", copyLocal: true), BuildReference.ByName("Remotion.Linq", copyLocal: true) }, Sources = { @" using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; namespace MyProject { internal class MyContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( ""Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MyProject.MyContext;Integrated Security=True"", b => b.MigrationsAssembly(""UnknownAssembly"")); } } namespace Migrations { [DbContext(typeof(MyContext))] [Migration(""20151215152142_MyMigration"")] public class MyMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { } } } }" } }; var build = source.Build(); using (var executor = new AppDomainOperationExecutor(targetDir, build.TargetName, targetDir, targetDir, "MyProject")) { var ex = Assert.Throws <OperationException>( () => executor.GetMigrations("MyContext")); Assert.Equal( ToolsCoreStrings.MigrationsAssemblyMismatch(build.TargetName, "UnknownAssembly"), ex.Message); } } }
// TODO: DRY (file names) public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotNull] string rootNamespace, bool force) { Check.NotEmpty(projectDir, nameof(projectDir)); Check.NotEmpty(rootNamespace, nameof(rootNamespace)); var files = new MigrationFiles(); var modelSnapshot = _migrationsAssembly.ModelSnapshot; if (modelSnapshot == null) { throw new InvalidOperationException(ToolsCoreStrings.NoSnapshot); } var language = _migrationCodeGenerator.FileExtension; IModel model = null; var migrations = _migrationsAssembly.Migrations .Select(m => _migrationsAssembly.CreateMigration(m.Value, _activeProvider)) .ToList(); if (migrations.Count != 0) { var migration = migrations[migrations.Count - 1]; model = migration.TargetModel; if (!_modelDiffer.HasDifferences(model, modelSnapshot.Model)) { if (force) { _logger.Value.LogWarning(ToolsCoreStrings.ForceRemoveMigration(migration.GetId())); } else if (_historyRepository.GetAppliedMigrations().Any( e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase))) { throw new InvalidOperationException(ToolsCoreStrings.UnapplyMigration(migration.GetId())); } var migrationFileName = migration.GetId() + language; var migrationFile = TryGetProjectFile(projectDir, migrationFileName); if (migrationFile != null) { _logger.Value.LogInformation(ToolsCoreStrings.RemovingMigration(migration.GetId())); File.Delete(migrationFile); files.MigrationFile = migrationFile; } else { _logger.Value.LogWarning(ToolsCoreStrings.NoMigrationFile(migrationFileName, migration.GetType().FullName)); } var migrationMetadataFileName = migration.GetId() + ".Designer" + language; var migrationMetadataFile = TryGetProjectFile(projectDir, migrationMetadataFileName); if (migrationMetadataFile != null) { File.Delete(migrationMetadataFile); files.MetadataFile = migrationMetadataFile; } else { _logger.Value.LogDebug(ToolsCoreStrings.NoMigrationMetadataFile(migrationMetadataFileName)); } model = migrations.Count > 1 ? migrations[migrations.Count - 2].TargetModel : null; } else { _logger.Value.LogDebug(ToolsCoreStrings.ManuallyDeleted); } } var modelSnapshotName = modelSnapshot.GetType().Name; var modelSnapshotFileName = modelSnapshotName + language; var modelSnapshotFile = TryGetProjectFile(projectDir, modelSnapshotFileName); if (model == null) { if (modelSnapshotFile != null) { _logger.Value.LogInformation(ToolsCoreStrings.RemovingSnapshot); File.Delete(modelSnapshotFile); files.SnapshotFile = modelSnapshotFile; } else { _logger.Value.LogWarning( ToolsCoreStrings.NoSnapshotFile(modelSnapshotFileName, modelSnapshot.GetType().FullName)); } } else { var modelSnapshotNamespace = modelSnapshot.GetType().Namespace; Debug.Assert(!string.IsNullOrEmpty(modelSnapshotNamespace)); var modelSnapshotCode = _migrationCodeGenerator.GenerateSnapshot( modelSnapshotNamespace, _contextType, modelSnapshotName, model); if (modelSnapshotFile == null) { modelSnapshotFile = Path.Combine( GetDirectory(projectDir, null, GetSubNamespace(rootNamespace, modelSnapshotNamespace)), modelSnapshotFileName); } _logger.Value.LogInformation(ToolsCoreStrings.RevertingSnapshot); File.WriteAllText(modelSnapshotFile, modelSnapshotCode, Encoding.UTF8); } return(files); }