Skip to content

Commit

Permalink
Merge pull request #43 from hexagram-solutions/respawner-in-reset-tool
Browse files Browse the repository at this point in the history
Reset database using Respawn in DB setup tool
  • Loading branch information
esond authored Feb 26, 2024
2 parents 0ba67fd + e4013bd commit e3fd8d8
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 86 deletions.
26 changes: 26 additions & 0 deletions build/Build.Deploy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.EntityFramework;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.EntityFramework.EntityFrameworkTasks;

// ReSharper disable InconsistentNaming

Expand All @@ -20,6 +22,12 @@ partial class Build

Project WebProject => Solution.GetAllProjects("Spenses.App").Single();

Target RestoreTools => t => t
.Executes(() =>
{
DotNetToolRestore(s => s);
});

Target Publish => t => t
.Description("Publish deployment artifacts.")
.Executes(() =>
Expand All @@ -31,6 +39,24 @@ partial class Build
.AddProperty("PublishProfile", "DefaultContainer")
.AddProperty("ContainerImageTags", GitVersion.NuGetVersionV2));
});
Project RelationalSetupTool => Solution.GetAllProjects("Spenses.Tools.Setup").Single();

Target MigrateDatabase => t => t
.Description("Migrate the SQL Server database to the latest version.")
.DependsOn(RestoreTools)
.Requires(() => SqlServerConnectionString)
.Executes(() =>
{
var dbContextProject = Solution.GetAllProjects("Spenses.Resources.Relational").Single();
EntityFrameworkDatabaseUpdate(s => s
.SetProject(dbContextProject)
.SetConnection(SqlServerConnectionString));
DotNetRun(s => s
.SetProjectFile(RelationalSetupTool)
.SetApplicationArguments($"views --connection \"{SqlServerConnectionString}\""));
});

Target AzureLogin => t => t
.Description("Log in with the Azure CLI.")
Expand Down
28 changes: 0 additions & 28 deletions build/Build.Test.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using Hexagrams.Nuke.Components;
using Nuke.Common;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.Coverlet;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.EntityFramework;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.EntityFramework.EntityFrameworkTasks;

partial class Build
{
Expand All @@ -19,31 +16,6 @@ partial class Build
public Configure<DotNetTestSettings> TestSettings => s => s
.SetExcludeByFile("\\\"*.Generated.cs,**/Resources/Relational/**.cs\\\"");

Target RestoreTools => t => t
.Executes(() =>
{
DotNetToolRestore(s => s);
});

Project RelationalSetupTool => Solution.GetAllProjects("Spenses.Tools.Setup").Single();

Target MigrateDatabase => t => t
.Description("Migrate the SQL Server database to the latest version.")
.DependsOn(RestoreTools)
.Requires(() => SqlServerConnectionString)
.Executes(() =>
{
var dbContextProject = Solution.GetAllProjects("Spenses.Resources.Relational").Single();
EntityFrameworkDatabaseUpdate(s => s
.SetProject(dbContextProject)
.SetConnection(SqlServerConnectionString));
DotNetRun(s => s
.SetProjectFile(RelationalSetupTool)
.SetApplicationArguments($"views --connection \"{SqlServerConnectionString}\""));
});

IEnumerable<Project> IntegrationTestProjects => Solution.GetAllProjects("*.IntegrationTests");

Target IntegrationTestSetup => t => t
Expand Down
77 changes: 20 additions & 57 deletions tools/Setup/DbSetupCommand.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System.CommandLine;
using System.Data.Common;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Respawn;
using Spenses.Resources.Relational;
using Spenses.Resources.Relational.Infrastructure;
using Spenses.Tools.Setup.SeedData;
Expand Down Expand Up @@ -71,14 +68,29 @@ private Command GetResetDatabaseCommand()

resetDatabaseCommand.SetHandler(async (connection, force, shouldSeed) =>
{
if (!await DropDatabase(connection, force))
await using var dbContext = CreateDbContext(connection);
await using var dbConnection = dbContext.Database.GetDbConnection();
if (!force && !Confirm($"Really reset '{dbConnection.DataSource}/{dbConnection.Database}'?"))
return;
await MigrateDatabase(connection);
await RebuildViews(connection);
await dbConnection.OpenAsync();
_logger.LogWarning("Resetting tables...");
var respawner = await Respawner.CreateAsync(dbConnection, new RespawnerOptions
{
CheckTemporalTables = true,
TablesToIgnore = ["__EFMigrationsHistory"]
});
await respawner.ResetAsync(dbConnection);
await MigrateDatabase(dbConnection.ConnectionString);
await RebuildViews(dbConnection.ConnectionString);
if (shouldSeed)
await SeedDatabase(connection);
await SeedDatabase(dbConnection.ConnectionString);
_logger.LogInformation("Done resetting database!");
}, ConnectionOption, forceOption, seedOption);
Expand All @@ -105,55 +117,6 @@ private async Task SeedDatabase(string connection)
_logger.LogInformation("Database seeded.");
}

public async Task<bool> DropDatabase(string connection, bool force)
{
await using var dbContext = CreateDbContext(connection);
await using var dbConnection = dbContext.Database.GetDbConnection();

if (!force && !Confirm($"Really drop '{dbConnection.DataSource}/{dbConnection.Database}'?"))
return false;

var db = GetSqlServerDatabase(dbConnection);

_logger.LogWarning("Dropping tables...");

var sql = string.Empty;

foreach (Table? table in db.Tables)
{
sql = table!.ForeignKeys.Cast<ForeignKey?>().Aggregate(sql,
(current, fk) => $"ALTER TABLE [{table.Name}] DROP CONSTRAINT [{fk!.Name}];\n" + current);

sql += $"DROP TABLE [{table.Name}];\n";
}
db.ExecuteNonQuery(sql);

_logger.LogWarning("Dropping views...");

foreach (var view in db.Views.Cast<View>().Where(v => !v.IsSystemObject))
{
db.ExecuteNonQuery($"DROP VIEW [{view!.Name}]");
}

_logger.LogWarning("Dropping sequences...");

foreach (var sequence in db.Sequences.Cast<Sequence>())
{
db.ExecuteNonQuery($"DROP SEQUENCE [{sequence!.Name}]");
}

return true;
}

private static Database GetSqlServerDatabase(DbConnection dbConnection)
{
var server = new Server(new ServerConnection((SqlConnection) dbConnection));

server.Refresh();

return server.Databases[dbConnection.Database];
}

private async Task MigrateDatabase(string connection)
{
await using var db = CreateDbContext(connection);
Expand Down
2 changes: 1 addition & 1 deletion tools/Setup/Spenses.Tools.Setup.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Microsoft.SqlServer.SqlManagementObjects" Version="170.23.0" />
<PackageReference Include="Respawn" Version="6.2.1" />
<PackageReference Include="Scrutor" Version="4.2.2" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>
Expand Down

0 comments on commit e3fd8d8

Please sign in to comment.