Skip to content

Commit

Permalink
Tools: Add Revert option to Remove-Migration
Browse files Browse the repository at this point in the history
Resolves #1972

Also updated T4 template for string resources generation. It had some weird issues.

Did manual verification with 1 or more migrations using PMC & dotnet ef both.
  • Loading branch information
smitpatel committed Nov 30, 2017
1 parent ac8c313 commit 6abe09e
Show file tree
Hide file tree
Showing 22 changed files with 173 additions and 49 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@
<data name="LogFoundTable" xml:space="preserve">
<value>Found table with name: {name}.</value>
<comment>Debug OracleEventId.TableFound string</comment>
</data>
</data>
<data name="LogFoundIndex" xml:space="preserve">
<value>Found index with name: {indexName}, table: {tableName}, is unique: {isUnique}.</value>
<comment>Debug OracleEventId.IndexFound string string bool</comment>
Expand All @@ -195,5 +195,8 @@
<data name="LogPrincipalColumnNotFound" xml:space="preserve">
<value>For foreign key {foreignKeyName} on table {tableName}, unable to find the column called {principalColumnName} on the foreign key's principal table, {principaltableName}. Skipping foreign key.</value>
<comment>Warning OracleEventId.ForeignKeyPrincipalColumnMissingWarning string string string string</comment>
</data>
</data>
<data name="InvalidTableToIncludeInScaffolding" xml:space="preserve">
<value>The specified table '{table}' is not valid. Specify tables using the format '[schema].[table]'.</value>
</data>
</root>
10 changes: 7 additions & 3 deletions src/EFCore.Design/Design/Internal/MigrationsOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ private string SubnamespaceFromOutputPath(string outputDir)
var subPath = outputDir.Substring(_projectDir.Length);

return !string.IsNullOrWhiteSpace(subPath)
? string.Join(".", subPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries))
? string.Join(
".",
subPath.Split(
new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar },
StringSplitOptions.RemoveEmptyEntries))
: null;
}

Expand Down Expand Up @@ -176,7 +180,7 @@ public virtual void UpdateDatabase(
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public virtual MigrationFiles RemoveMigration(
[CanBeNull] string contextType, bool force)
[CanBeNull] string contextType, bool force, bool revert)
{
using (var context = _contextOperations.CreateContext(contextType))
{
Expand All @@ -186,7 +190,7 @@ public virtual MigrationFiles RemoveMigration(

var scaffolder = services.GetRequiredService<MigrationsScaffolder>();

var files = scaffolder.RemoveMigration(_projectDir, _rootNamespace, force, _language);
var files = scaffolder.RemoveMigration(_projectDir, _rootNamespace, force, revert, _language);

_reporter.WriteInformation(DesignStrings.Done);

Expand Down
7 changes: 4 additions & 3 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,15 +295,16 @@ public RemoveMigration(

var contextType = (string)args["contextType"];
var force = (bool)args["force"];
var revert = (bool)args["revert"];

Execute(() => executor.RemoveMigrationImpl(contextType, force));
Execute(() => executor.RemoveMigrationImpl(contextType, force, revert));
}
}

private IDictionary RemoveMigrationImpl([CanBeNull] string contextType, bool force)
private IDictionary RemoveMigrationImpl([CanBeNull] string contextType, bool force, bool revert)
{
var files = _migrationsOperations.Value
.RemoveMigration(contextType, force);
.RemoveMigration(contextType, force, revert);

return new Hashtable
{
Expand Down
17 changes: 15 additions & 2 deletions src/EFCore.Design/Migrations/Design/MigrationsScaffolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,23 @@ protected virtual string GetSubNamespace([NotNull] string rootNamespace, [NotNul
/// <param name="force"> Don't check to see if the migration has been applied to the database. </param>
/// <returns> The removed migration files. </returns>
public virtual MigrationFiles RemoveMigration([NotNull] string projectDir, [NotNull] string rootNamespace, bool force)
=> RemoveMigration(projectDir, rootNamespace, force, language: null);
=> RemoveMigration(projectDir, rootNamespace, force, revert: false, language: null);

/// <summary>
/// Removes the previous migration.
/// </summary>
/// <param name="projectDir"> The project's root directory. </param>
/// <param name="rootNamespace"> The project's root namespace. </param>
/// <param name="force"> Don't check to see if the migration has been applied to the database. </param>
/// <param name="revert"> Revert if the migration has been applied to the database before removing. </param>
/// <param name="language"> The project's language. </param>
/// <returns> The removed migration files. </returns>
// TODO: DRY (file names)
public virtual MigrationFiles RemoveMigration(
[NotNull] string projectDir,
[NotNull] string rootNamespace,
bool force,
bool revert,
[CanBeNull] string language)
{
Check.NotEmpty(projectDir, nameof(projectDir));
Expand Down Expand Up @@ -254,7 +256,18 @@ public virtual MigrationFiles RemoveMigration(
else if (Dependencies.HistoryRepository.GetAppliedMigrations().Any(
e => e.MigrationId.Equals(migration.GetId(), StringComparison.OrdinalIgnoreCase)))
{
throw new OperationException(DesignStrings.RevertMigration(migration.GetId()));
if (revert)
{
Dependencies.OperationReporter.WriteInformation(DesignStrings.RevertingMigration(migration.GetId()));
Dependencies.Migrator.Migrate(
migrations.Count > 1
? migrations[migrations.Count - 2].GetId()
: Migration.InitialDatabase);
}
else
{
throw new OperationException(DesignStrings.RevertMigration(migration.GetId()));
}
}

var migrationFileName = migration.GetId() + codeGenerator.FileExtension;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public sealed class MigrationsScaffolderDependencies
/// <param name="operationReporter"> The operation reporter. </param>
/// <param name="databaseProvider"> The database provider. </param>
/// <param name="snapshotModelProcessor"> The snapshot model processor. </param>
/// <param name="migrator"> The migrator. </param>
public MigrationsScaffolderDependencies(
[NotNull] ICurrentDbContext currentDbContext,
[NotNull] IModel model,
Expand All @@ -68,7 +69,8 @@ public MigrationsScaffolderDependencies(
[NotNull] IHistoryRepository historyRepository,
[NotNull] IOperationReporter operationReporter,
[NotNull] IDatabaseProvider databaseProvider,
[NotNull] ISnapshotModelProcessor snapshotModelProcessor)
[NotNull] ISnapshotModelProcessor snapshotModelProcessor,
[NotNull] IMigrator migrator)
{
Check.NotNull(currentDbContext, nameof(currentDbContext));
Check.NotNull(model, nameof(model));
Expand All @@ -80,6 +82,7 @@ public MigrationsScaffolderDependencies(
Check.NotNull(operationReporter, nameof(operationReporter));
Check.NotNull(databaseProvider, nameof(databaseProvider));
Check.NotNull(snapshotModelProcessor, nameof(snapshotModelProcessor));
Check.NotNull(migrator, nameof(migrator));

CurrentDbContext = currentDbContext;
Model = model;
Expand All @@ -91,6 +94,7 @@ public MigrationsScaffolderDependencies(
OperationReporter = operationReporter;
DatabaseProvider = databaseProvider;
SnapshotModelProcessor = snapshotModelProcessor;
Migrator = migrator;
}

/// <summary>
Expand Down Expand Up @@ -150,6 +154,11 @@ public IMigrationsCodeGenerator MigrationCodeGenerator
/// </summary>
public ISnapshotModelProcessor SnapshotModelProcessor { get; }

/// <summary>
/// The migrator.
/// </summary>
public IMigrator Migrator { get; }

/// <summary>
/// Clones this dependency parameter object with one service replaced.
/// </summary>
Expand All @@ -166,7 +175,8 @@ public MigrationsScaffolderDependencies With([NotNull] ICurrentDbContext current
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -184,7 +194,8 @@ public MigrationsScaffolderDependencies With([NotNull] IModel model)
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -202,7 +213,8 @@ public MigrationsScaffolderDependencies With([NotNull] IMigrationsAssembly migra
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -220,7 +232,8 @@ public MigrationsScaffolderDependencies With([NotNull] IMigrationsModelDiffer mi
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -238,7 +251,8 @@ public MigrationsScaffolderDependencies With([NotNull] IMigrationsIdGenerator mi
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand Down Expand Up @@ -269,7 +283,8 @@ public MigrationsScaffolderDependencies With([NotNull] MigrationsCodeGeneratorSe
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -287,7 +302,8 @@ public MigrationsScaffolderDependencies With([NotNull] IHistoryRepository histor
historyRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -305,7 +321,8 @@ public MigrationsScaffolderDependencies With([NotNull] IOperationReporter operat
HistoryRepository,
operationReporter,
DatabaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -323,7 +340,8 @@ public MigrationsScaffolderDependencies With([NotNull] IDatabaseProvider databas
HistoryRepository,
OperationReporter,
databaseProvider,
SnapshotModelProcessor);
SnapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
Expand All @@ -341,6 +359,26 @@ public MigrationsScaffolderDependencies With([NotNull] ISnapshotModelProcessor s
HistoryRepository,
OperationReporter,
DatabaseProvider,
snapshotModelProcessor);
snapshotModelProcessor,
Migrator);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
/// </summary>
/// <param name="migrator"> A replacement for the current dependency of this type. </param>
/// <returns> A new parameter object with the given service replaced. </returns>
public MigrationsScaffolderDependencies With([NotNull] IMigrator migrator)
=> new MigrationsScaffolderDependencies(
CurrentDbContext,
Model,
MigrationsAssembly,
MigrationsModelDiffer,
MigrationsIdGenerator,
MigrationCodeGeneratorSelector,
HistoryRepository,
OperationReporter,
DatabaseProvider,
SnapshotModelProcessor,
migrator);
}
}
16 changes: 8 additions & 8 deletions src/EFCore.Design/Properties/DesignStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/EFCore.Design/Properties/DesignStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,7 @@ Change your target project to the migrations project by using the Package Manage
<data name="NoLanguageService" xml:space="preserve">
<value>The project language '{language}' isn't supported by the built-in {service} service. You can try looking for an additional NuGet package which supports this language; moving your DbContext type to a C# class library referenced by this project; or manually implementing and registering the design-time service for programming language.</value>
</data>
<data name="RevertingMigration" xml:space="preserve">
<value>Reverting migration '{name}'.</value>
</data>
</root>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion src/EFCore.Tools/tools/EntityFrameworkCore.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ Register-TabExpansion Remove-Migration @{
.PARAMETER Force
Don't check to see if the migration has been applied to the database. Always implied on UWP apps.
.PARAMETER Revert
Revert the migration if it has been applied to the database.
.PARAMETER Context
The DbContext to use.
Expand All @@ -215,7 +218,7 @@ Register-TabExpansion Remove-Migration @{
function Remove-Migration
{
[CmdletBinding(PositionalBinding = $false)]
param([switch] $Force, [string] $Context, [string] $Project, [string] $StartupProject)
param([switch] $Force, [switch] $Revert, [string] $Context, [string] $Project, [string] $StartupProject)

$dteProject = GetProject $Project
$dteStartupProject = GetStartupProject $StartupProject $dteProject
Expand All @@ -227,6 +230,11 @@ function Remove-Migration
$params += '--force'
}

if ($Revert)
{
$params += '--revert'
}

$params += GetParams $Context

# NB: -join is here to support ConvertFrom-Json on PowerShell 3.0
Expand Down
7 changes: 7 additions & 0 deletions src/dotnet-ef/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/dotnet-ef/Properties/Resources.Designer.tt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<#
Session["ResourceFile"] = "Resources.resx";
Session["AccessModifier"] = "internal";
Session["NoDiagnostics"] = true;
#>
<#@ include file="..\..\..\tools\Resources.tt" #>
Loading

0 comments on commit 6abe09e

Please sign in to comment.