Merged PR 35: Migration service can keep its metadata from now in multiple locations: XmlFile or Database (SqlServer or Sqlite)
- Database metadata location - added migration tables - MigrationSignaturesService - MigrationSignaturesService - Migration service can keep its metadata from now in multiple locations: XmlFile or Database (SqlServer or Sqlite)messaging
parent
92632050d7
commit
f9bb922c01
|
@ -4,6 +4,10 @@
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Scripts\01.Test.sql" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -15,4 +19,22 @@
|
||||||
<ProjectReference Include="..\test\NDB.Test.Application\NDB.Test.Application.csproj" />
|
<ProjectReference Include="..\test\NDB.Test.Application\NDB.Test.Application.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Scripts\3.3.3\01.Test.sql">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Scripts\3.3.4\01.Test-new-ver.sql">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Scripts\3.3.4\02.Test-new-ver-2.sql">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Scripts\4.0.0\01.Major changes.sql">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Scripts\4.0.0\02.Last script.sql">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
select 'Test script!'
|
|
@ -0,0 +1 @@
|
||||||
|
select 'Test script!'
|
|
@ -0,0 +1 @@
|
||||||
|
select 'Test script!'
|
|
@ -0,0 +1 @@
|
||||||
|
select 'Test script!'
|
|
@ -0,0 +1 @@
|
||||||
|
select 'Test script!'
|
|
@ -3,10 +3,10 @@ using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using NDB.Extensions.Swagger;
|
using NDB.Extensions.Swagger;
|
||||||
using NDB.Extensions.Swagger.Constants;
|
using NDB.Extensions.Swagger.Constants;
|
||||||
using NDB.Infrastructure.DatabaseMigration;
|
using NDB.Infrastructure.DatabaseMigration;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Constants;
|
||||||
using NDB.Test.Api.Extensions;
|
using NDB.Test.Api.Extensions;
|
||||||
|
|
||||||
namespace NDB.Test.Api
|
namespace NDB.Test.Api
|
||||||
|
@ -29,7 +29,7 @@ namespace NDB.Test.Api
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
services.AddSwagger("NDB.Test.Api", AuthorizationType.InhouseIdentity);
|
services.AddSwagger("NDB.Test.Api", AuthorizationType.InhouseIdentity);
|
||||||
|
|
||||||
services.AddMigration();
|
services.AddMigration(DatabaseType.SQLite, MetadataLocation.Database);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"DatabaseConnection": "Data Source={Workspace}\\TesterDb.db"
|
|
||||||
//"DatabaseConnection": "***REMOVED***"
|
//"DatabaseConnection": "***REMOVED***"
|
||||||
|
//"DatabaseConnection": "***REMOVED***"
|
||||||
|
"DatabaseConnection": "Data Source={Workspace}\\NDB_TESTER.db"
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Constants
|
||||||
|
{
|
||||||
|
internal struct ManifestResourcesPath
|
||||||
|
{
|
||||||
|
public const string
|
||||||
|
SqlServer = "NDB.Infrastructure.DatabaseMigration.Scripts.SqlServer.",
|
||||||
|
Sqlite = "NDB.Infrastructure.DatabaseMigration.Scripts.Sqlite.";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct ManifestResources
|
||||||
|
{
|
||||||
|
public static string[]
|
||||||
|
SqlServer = new string[] { "01.CreateMigrationSchema.sql", "02.MigrationTables.sql" },
|
||||||
|
Sqlite = new string[] { "01.MigrationSignatureTable.sql", "02.MigratedVersionTable.sql", "03.MigratedScriptTable.sql" };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Constants
|
||||||
|
{
|
||||||
|
public enum MetadataLocation
|
||||||
|
{
|
||||||
|
XmlFile,
|
||||||
|
Database
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Entities;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Entities.Configurations;
|
||||||
|
|
||||||
namespace NDB.Infrastructure.DatabaseMigration.DbContexts
|
namespace NDB.Infrastructure.DatabaseMigration.DbContexts
|
||||||
{
|
{
|
||||||
|
@ -8,9 +10,15 @@ namespace NDB.Infrastructure.DatabaseMigration.DbContexts
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DbSet<MigrationSignature> MigrationSignatures { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.ApplyConfiguration(new MigratedScriptConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new MigratedVersionConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new MigrationSignatureConfiguration());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using NDB.Infrastructure.DatabaseMigration.DbContexts;
|
||||||
using NDB.Infrastructure.DatabaseMigration.Models;
|
using NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
||||||
using NDB.Infrastructure.DatabaseMigration.Services;
|
using NDB.Infrastructure.DatabaseMigration.Services;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Services.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace NDB.Infrastructure.DatabaseMigration
|
namespace NDB.Infrastructure.DatabaseMigration
|
||||||
|
@ -17,13 +18,16 @@ namespace NDB.Infrastructure.DatabaseMigration
|
||||||
|
|
||||||
public static void AddMigration(this IServiceCollection services,
|
public static void AddMigration(this IServiceCollection services,
|
||||||
DatabaseType databaseType = DatabaseType.SQLite,
|
DatabaseType databaseType = DatabaseType.SQLite,
|
||||||
|
MetadataLocation metadataLocation = MetadataLocation.XmlFile,
|
||||||
string connectionName = "DatabaseConnection",
|
string connectionName = "DatabaseConnection",
|
||||||
string workspace = "Workspace",
|
string workspace = "Workspace",
|
||||||
string scriptsDirectoryPath = "Scripts")
|
string scriptsDirectoryPath = "Scripts")
|
||||||
{
|
{
|
||||||
var serviceConfiguration = new ServiceConfiguration(databaseType, connectionName, workspace, scriptsDirectoryPath);
|
var serviceConfiguration = new ServiceConfiguration(databaseType, metadataLocation, connectionName, workspace, scriptsDirectoryPath);
|
||||||
services.AddSingleton(serviceConfiguration);
|
services.AddSingleton(serviceConfiguration);
|
||||||
services.AddDataAccess(serviceConfiguration);
|
services.AddDataAccess(serviceConfiguration);
|
||||||
|
services.AddSingleton<IMetadataLocationService, MetadataLocationService>();
|
||||||
|
services.AddSingleton<IMigrationSignaturesService, MigrationSignaturesService>();
|
||||||
services.AddSingleton<IMigrationService, MigrationService>();
|
services.AddSingleton<IMigrationService, MigrationService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities.Configurations
|
||||||
|
{
|
||||||
|
internal class MigratedScriptConfiguration : IEntityTypeConfiguration<MigratedScript>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<MigratedScript> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("MigratedScript", "migration").HasKey(z => z.Id);
|
||||||
|
builder.Property(z => z.Id).ValueGeneratedOnAdd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities.Configurations
|
||||||
|
{
|
||||||
|
internal class MigratedVersionConfiguration : IEntityTypeConfiguration<MigratedVersion>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<MigratedVersion> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("MigratedVersion", "migration").HasKey(z => z.Id);
|
||||||
|
builder.Property(z => z.Id).ValueGeneratedOnAdd();
|
||||||
|
builder.HasMany(z => z.Scripts).WithOne().HasForeignKey(z => z.VersionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities.Configurations
|
||||||
|
{
|
||||||
|
internal class MigrationSignatureConfiguration : IEntityTypeConfiguration<MigrationSignature>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<MigrationSignature> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("MigrationSignature", "migration").HasKey(z => z.Id);
|
||||||
|
builder.Property(z => z.Id).ValueGeneratedOnAdd();
|
||||||
|
builder.HasMany(z => z.MigratedVersions).WithOne().HasForeignKey(z => z.SignatureId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities
|
||||||
|
{
|
||||||
|
internal class MigratedScript
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int VersionId { get; set; }
|
||||||
|
public string Script { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities
|
||||||
|
{
|
||||||
|
internal class MigratedVersion
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SignatureId { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
public ICollection<MigratedScript> Scripts { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Entities
|
||||||
|
{
|
||||||
|
internal class MigrationSignature
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public DateTime MigrationDate { get; set; }
|
||||||
|
public string MachineName { get; set; }
|
||||||
|
public string LastVersion { get; set; }
|
||||||
|
|
||||||
|
public ICollection<MigratedVersion> MigratedVersions { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Linq;
|
||||||
|
using e = NDB.Infrastructure.DatabaseMigration.Entities;
|
||||||
|
using m = NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Extensions
|
||||||
|
{
|
||||||
|
internal static class Mappings
|
||||||
|
{
|
||||||
|
public static m.MigratedVersion ToModel(this e.MigratedVersion migratedVersion)
|
||||||
|
{
|
||||||
|
return new m.MigratedVersion()
|
||||||
|
{
|
||||||
|
Version = migratedVersion.Version,
|
||||||
|
Scripts = migratedVersion.Scripts.Select(z => z.Script).ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static m.MigrationSignature ToModel(this e.MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
return new m.MigrationSignature()
|
||||||
|
{
|
||||||
|
MigrationDate = migrationSignature.MigrationDate,
|
||||||
|
MachineName = migrationSignature.MachineName,
|
||||||
|
LastVersion = migrationSignature.LastVersion,
|
||||||
|
MigratedVersions = migrationSignature.MigratedVersions.Select(z => z.ToModel()).ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static e.MigratedVersion ToEntity(this m.MigratedVersion migratedVersion)
|
||||||
|
{
|
||||||
|
return new e.MigratedVersion()
|
||||||
|
{
|
||||||
|
Version = migratedVersion.Version,
|
||||||
|
Scripts = migratedVersion.Scripts.Select(z => new e.MigratedScript() { Script = z }).ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static e.MigrationSignature ToEntity(this m.MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
return new e.MigrationSignature()
|
||||||
|
{
|
||||||
|
MigrationDate = migrationSignature.MigrationDate,
|
||||||
|
MachineName = migrationSignature.MachineName,
|
||||||
|
LastVersion = migrationSignature.LastVersion,
|
||||||
|
MigratedVersions = migrationSignature.MigratedVersions.Select(z => z.ToEntity()).ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<MigrationThumbprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<MigrationSignatures>
|
||||||
|
<MigrationSignature>
|
||||||
|
<MigrationDate>2022-02-10T20:20:42.2487339+02:00</MigrationDate>
|
||||||
|
<MachineName>TS1926</MachineName>
|
||||||
|
<MigratedVersions>
|
||||||
|
<MigratedVersion>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Scripts>
|
||||||
|
<string>01.UserStatus table.sql</string>
|
||||||
|
<string>02.AppUser table.sql</string>
|
||||||
|
<string>03.IDX_AppUser_Email_NOTNULL.sql</string>
|
||||||
|
</Scripts>
|
||||||
|
</MigratedVersion>
|
||||||
|
<MigratedVersion>
|
||||||
|
<Version>1.0.1</Version>
|
||||||
|
<Scripts>
|
||||||
|
<string>01.UserClaim table.sql</string>
|
||||||
|
<string>02.UserToken table.sql</string>
|
||||||
|
<string>03.Add admin user.sql</string>
|
||||||
|
<string>04.Add my user.sql</string>
|
||||||
|
</Scripts>
|
||||||
|
</MigratedVersion>
|
||||||
|
</MigratedVersions>
|
||||||
|
<LastVersion>1.0.1</LastVersion>
|
||||||
|
</MigrationSignature>
|
||||||
|
</MigrationSignatures>
|
||||||
|
</MigrationThumbprint>
|
|
@ -5,13 +5,15 @@ namespace NDB.Infrastructure.DatabaseMigration.Models
|
||||||
internal class ServiceConfiguration
|
internal class ServiceConfiguration
|
||||||
{
|
{
|
||||||
public DatabaseType DatabaseType { get; }
|
public DatabaseType DatabaseType { get; }
|
||||||
|
public MetadataLocation MetadataLocation { get; }
|
||||||
public string ConnectionName { get; }
|
public string ConnectionName { get; }
|
||||||
public string Workspace { get; }
|
public string Workspace { get; }
|
||||||
public string ScriptsDirectory { get; }
|
public string ScriptsDirectory { get; }
|
||||||
|
|
||||||
public ServiceConfiguration(DatabaseType databaseType, string connectionName, string workspace, string scriptsDirectory)
|
public ServiceConfiguration(DatabaseType databaseType, MetadataLocation metadataLocation, string connectionName, string workspace, string scriptsDirectory)
|
||||||
{
|
{
|
||||||
DatabaseType = databaseType;
|
DatabaseType = databaseType;
|
||||||
|
MetadataLocation = metadataLocation;
|
||||||
ConnectionName = connectionName;
|
ConnectionName = connectionName;
|
||||||
Workspace = workspace;
|
Workspace = workspace;
|
||||||
ScriptsDirectory = scriptsDirectory;
|
ScriptsDirectory = scriptsDirectory;
|
||||||
|
|
|
@ -10,6 +10,22 @@
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Scripts\Sqlite\01.MigrationSignatureTable.sql" />
|
||||||
|
<None Remove="Scripts\Sqlite\02.MigratedVersionTable.sql" />
|
||||||
|
<None Remove="Scripts\Sqlite\03.MigratedScriptTable.sql" />
|
||||||
|
<None Remove="Scripts\SqlServer\01.CreateMigrationSchema.sql" />
|
||||||
|
<None Remove="Scripts\SqlServer\02.MigrationTables.sql" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Scripts\Sqlite\03.MigratedScriptTable.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\Sqlite\02.MigratedVersionTable.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\Sqlite\01.MigrationSignatureTable.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\SqlServer\02.MigrationTables.sql" />
|
||||||
|
<EmbeddedResource Include="Scripts\SqlServer\01.CreateMigrationSchema.sql" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.13" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.13" />
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
using System.Threading.Tasks;
|
using NDB.Infrastructure.DatabaseMigration.Constants;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Entities;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NDB.Infrastructure.DatabaseMigration.Repositories
|
namespace NDB.Infrastructure.DatabaseMigration.Repositories
|
||||||
{
|
{
|
||||||
public interface IMigrationRepository
|
internal interface IMigrationRepository
|
||||||
{
|
{
|
||||||
Task ExecuteSqlRaw(string sqlRaw);
|
Task ExecuteSqlRaw(string sqlRaw);
|
||||||
|
Task<bool> MigrationTablesAreSet(DatabaseType databaseType);
|
||||||
|
Task<MigrationSignature> GetLastMigrationSignature();
|
||||||
|
Task AddMigrationSignature(MigrationSignature migrationSignature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Constants;
|
||||||
using NDB.Infrastructure.DatabaseMigration.DbContexts;
|
using NDB.Infrastructure.DatabaseMigration.DbContexts;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NDB.Infrastructure.DatabaseMigration.Repositories
|
namespace NDB.Infrastructure.DatabaseMigration.Repositories
|
||||||
|
@ -17,5 +21,40 @@ namespace NDB.Infrastructure.DatabaseMigration.Repositories
|
||||||
{
|
{
|
||||||
await _dbContext.Database.ExecuteSqlRawAsync(sqlRaw);
|
await _dbContext.Database.ExecuteSqlRawAsync(sqlRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> MigrationTablesAreSet(DatabaseType databaseType)
|
||||||
|
{
|
||||||
|
var query = databaseType switch
|
||||||
|
{
|
||||||
|
DatabaseType.SQLServer => "select count(1) from sys.objects where name = 'MigrationSignature' and type = 'U' and SCHEMA_NAME(schema_id)='migration'",
|
||||||
|
DatabaseType.SQLite => "select count(1) from sqlite_master where type='table' and name='MigrationSignature';",
|
||||||
|
_ => throw new NotImplementedException($"DatabaseMigration type {databaseType} is not implemented"),
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var command = _dbContext.Database.GetDbConnection().CreateCommand())
|
||||||
|
{
|
||||||
|
command.CommandText = query;
|
||||||
|
await _dbContext.Database.OpenConnectionAsync();
|
||||||
|
var result = await command.ExecuteScalarAsync();
|
||||||
|
|
||||||
|
return result != null && result != DBNull.Value && Convert.ToInt32(result) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<MigrationSignature> GetLastMigrationSignature()
|
||||||
|
{
|
||||||
|
var query = _dbContext.MigrationSignatures
|
||||||
|
.Include(z => z.MigratedVersions).ThenInclude(z => z.Scripts)
|
||||||
|
.OrderByDescending(z => z.MigrationDate)
|
||||||
|
.AsSplitQuery();
|
||||||
|
|
||||||
|
return query.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMigrationSignature(MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
await _dbContext.MigrationSignatures.AddAsync(migrationSignature);
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
if not exists (select top 1 1 from sys.schemas where name = 'migration')
|
||||||
|
begin
|
||||||
|
EXEC ('CREATE SCHEMA [migration] AUTHORIZATION [dbo]')
|
||||||
|
end
|
|
@ -0,0 +1,30 @@
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'MigrationSignature' and type = 'U' and SCHEMA_NAME(schema_id) = 'migration')
|
||||||
|
begin
|
||||||
|
create table migration.MigrationSignature
|
||||||
|
(
|
||||||
|
Id int identity(1, 1) constraint PK_MigrationSignature primary key,
|
||||||
|
MigrationDate Datetime not null,
|
||||||
|
MachineName varchar(30) not null,
|
||||||
|
LastVersion varchar(20) not null
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'MigratedVersion' and type = 'U' and SCHEMA_NAME(schema_id) = 'migration')
|
||||||
|
begin
|
||||||
|
create table migration.MigratedVersion
|
||||||
|
(
|
||||||
|
Id int identity(1, 1) constraint PK_MigratedVersion primary key,
|
||||||
|
SignatureId int constraint FK_MigratedVersion_MigrationSignature foreign key references migration.MigrationSignature(Id),
|
||||||
|
[Version] varchar(20) not null
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'MigratedScript' and type = 'U' and SCHEMA_NAME(schema_id) = 'migration')
|
||||||
|
begin
|
||||||
|
create table migration.MigratedScript
|
||||||
|
(
|
||||||
|
Id int identity(1, 1) constraint PK_MigratedScript primary key,
|
||||||
|
VersionId int constraint FK_MigratedScript_MigratedVersion foreign key references migration.MigratedVersion(Id),
|
||||||
|
Script varchar(250) not null
|
||||||
|
)
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE "MigrationSignature" (
|
||||||
|
"Id" INTEGER NOT NULL,
|
||||||
|
"MigrationDate" TEXT NOT NULL,
|
||||||
|
"MachineName" TEXT NOT NULL,
|
||||||
|
"LastVersion" TEXT NOT NULL,
|
||||||
|
CONSTRAINT "PK_MigrationSignature" PRIMARY KEY("Id" AUTOINCREMENT)
|
||||||
|
);
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE "MigratedVersion" (
|
||||||
|
"Id" INTEGER NOT NULL,
|
||||||
|
"SignatureId" INTEGER,
|
||||||
|
"Version" TEXT NOT NULL,
|
||||||
|
CONSTRAINT "PK_MigratedVersion" PRIMARY KEY("Id" AUTOINCREMENT),
|
||||||
|
CONSTRAINT "FK_MigratedVersion_MigrationSignature" FOREIGN KEY("SignatureId") REFERENCES "MigrationSignature"("Id")
|
||||||
|
);
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE "MigratedScript" (
|
||||||
|
"Id" INTEGER NOT NULL,
|
||||||
|
"VersionId" INTEGER,
|
||||||
|
"Script" TEXT NOT NULL,
|
||||||
|
CONSTRAINT "PK_MigratedScript" PRIMARY KEY("Id" AUTOINCREMENT),
|
||||||
|
CONSTRAINT "FK_MigratedScript_MigratedVersion" FOREIGN KEY("VersionId") REFERENCES "MigratedVersion"("Id")
|
||||||
|
);
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Services.Abstractions
|
||||||
|
{
|
||||||
|
internal interface IMetadataLocationService
|
||||||
|
{
|
||||||
|
Task Check();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
namespace NDB.Infrastructure.DatabaseMigration.Services
|
namespace NDB.Infrastructure.DatabaseMigration.Services.Abstractions
|
||||||
{
|
{
|
||||||
public interface IMigrationService
|
public interface IMigrationService
|
||||||
{
|
{
|
|
@ -0,0 +1,11 @@
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Services.Abstractions
|
||||||
|
{
|
||||||
|
internal interface IMigrationSignaturesService
|
||||||
|
{
|
||||||
|
Task<MigrationSignature> GetLastMigrationSignature();
|
||||||
|
Task SaveMigrationSignature(MigrationSignature migrationSignature);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Constants;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Services.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
|
{
|
||||||
|
internal class MetadataLocationService : IMetadataLocationService
|
||||||
|
{
|
||||||
|
private readonly ServiceConfiguration _configuration;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly ILogger<MetadataLocationService> _logger;
|
||||||
|
|
||||||
|
public MetadataLocationService(ServiceConfiguration configuration, IServiceProvider serviceProvider, ILogger<MetadataLocationService> logger)
|
||||||
|
{
|
||||||
|
_configuration=configuration;
|
||||||
|
_serviceProvider=serviceProvider;
|
||||||
|
_logger=logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Check()
|
||||||
|
{
|
||||||
|
switch (_configuration.MetadataLocation)
|
||||||
|
{
|
||||||
|
case MetadataLocation.XmlFile:
|
||||||
|
CheckWorkspace();
|
||||||
|
break;
|
||||||
|
case MetadataLocation.Database:
|
||||||
|
await CheckMigrationTables();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"Metadata location {_configuration.MetadataLocation} is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckWorkspace()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_configuration.Workspace))
|
||||||
|
throw new Exception($"Workspace path is empty! Check 'Workspace' parameter.");
|
||||||
|
|
||||||
|
if (!Directory.Exists(_configuration.Workspace))
|
||||||
|
Directory.CreateDirectory(_configuration.Workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckMigrationTables()
|
||||||
|
{
|
||||||
|
using (var scope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var _repository = scope.ServiceProvider.GetRequiredService<IMigrationRepository>();
|
||||||
|
var migrationTablesAreSet = await _repository.MigrationTablesAreSet(_configuration.DatabaseType);
|
||||||
|
if (migrationTablesAreSet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
var allEmbeddedResources = assembly.GetManifestResourceNames();
|
||||||
|
|
||||||
|
var sqlResources = GetSqlResources();
|
||||||
|
foreach (var resource in sqlResources)
|
||||||
|
{
|
||||||
|
if (!allEmbeddedResources.Contains(resource))
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"Manifest resource {resource} does not exists in assembly {assembly.FullName} and will be ignored.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resourceContent = GetManifestResourceContent(assembly, resource);
|
||||||
|
await _repository.ExecuteSqlRaw(resourceContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetSqlResources()
|
||||||
|
{
|
||||||
|
var result = _configuration.DatabaseType switch
|
||||||
|
{
|
||||||
|
DatabaseType.SQLServer => ManifestResources.SqlServer.Select(resource => $"{ManifestResourcesPath.SqlServer}{resource}"),
|
||||||
|
DatabaseType.SQLite => ManifestResources.Sqlite.Select(resource => $"{ManifestResourcesPath.Sqlite}{resource}"),
|
||||||
|
_ => throw new NotImplementedException($"DatabaseMigration type {_configuration.DatabaseType} is not implemented"),
|
||||||
|
};
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetManifestResourceContent(Assembly assembly, string resourceName)
|
||||||
|
{
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
string result = reader.ReadToEnd();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,73 +2,42 @@
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using NDB.Infrastructure.DatabaseMigration.Models;
|
using NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Services.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace NDB.Infrastructure.DatabaseMigration.Services
|
namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
{
|
{
|
||||||
internal class MigrationService : IMigrationService
|
internal class MigrationService : IMigrationService
|
||||||
{
|
{
|
||||||
private readonly string _migrationSignaturesFilePath;
|
|
||||||
private const string _migrationSignaturesFileName = "MigrationSignatures.xml";
|
|
||||||
private readonly ILogger<MigrationService> _logger;
|
private readonly ILogger<MigrationService> _logger;
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly ServiceConfiguration _configuration;
|
private readonly ServiceConfiguration _configuration;
|
||||||
|
private readonly IMetadataLocationService _metadataLocationService;
|
||||||
|
private readonly IMigrationSignaturesService _migrationSignaturesService;
|
||||||
|
|
||||||
public MigrationService(ILogger<MigrationService> logger, IServiceProvider serviceProvider, ServiceConfiguration configuration)
|
public MigrationService(ILogger<MigrationService> logger, IServiceProvider serviceProvider, ServiceConfiguration configuration, IMetadataLocationService metadataLocationService, IMigrationSignaturesService migrationSignaturesService)
|
||||||
{
|
{
|
||||||
_migrationSignaturesFilePath = Path.Combine(configuration.Workspace, _migrationSignaturesFileName);
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
_metadataLocationService = metadataLocationService;
|
||||||
|
_migrationSignaturesService = migrationSignaturesService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckWorkspace()
|
public void Execute() => ExecuteAsync().GetAwaiter().GetResult();
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_configuration.Workspace))
|
|
||||||
throw new Exception($"Workspace path is empty! Check 'Workspace' parameter.");
|
|
||||||
|
|
||||||
if (!Directory.Exists(_configuration.Workspace))
|
private async Task ExecuteAsync()
|
||||||
Directory.CreateDirectory(_configuration.Workspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MigrationSignature[] GetMigrationSignatures()
|
|
||||||
{
|
|
||||||
if (!File.Exists(_migrationSignaturesFilePath))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var serializer = new XmlSerializer(typeof(MigrationThumbprint));
|
|
||||||
using (var reader = XmlReader.Create(_migrationSignaturesFilePath))
|
|
||||||
{
|
|
||||||
var migrationSignatureRoot = (MigrationThumbprint)serializer.Deserialize(reader);
|
|
||||||
return migrationSignatureRoot.MigrationSignatures;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveMigrationSignatures(MigrationSignature[] migrationSignatures)
|
|
||||||
{
|
|
||||||
var root = new MigrationThumbprint() { MigrationSignatures = migrationSignatures };
|
|
||||||
var serializer = new XmlSerializer(root.GetType());
|
|
||||||
var settings = new XmlWriterSettings() { Indent = true };
|
|
||||||
using (var writer = XmlWriter.Create(_migrationSignaturesFilePath, settings))
|
|
||||||
{
|
|
||||||
serializer.Serialize(writer, root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Execute()
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Starting migration...");
|
_logger.LogInformation("Starting migration...");
|
||||||
|
|
||||||
CheckWorkspace();
|
await _metadataLocationService.Check();
|
||||||
|
|
||||||
var localSignatures = GetMigrationSignatures();
|
var lastSignature = await _migrationSignaturesService.GetLastMigrationSignature();
|
||||||
var lastInstalledVersion = localSignatures?.OrderByDescending(z => z.MigrationDate).FirstOrDefault()?.LastVersion ?? "0.0.0";
|
var lastInstalledVersion = lastSignature?.LastVersion ?? "0.0.0";
|
||||||
var targetVersion = new Version(lastInstalledVersion);
|
var targetVersion = new Version(lastInstalledVersion);
|
||||||
var scriptPacks = GetScriptPacks();
|
var scriptPacks = GetScriptPacks();
|
||||||
var packsToInstall = scriptPacks.Where(p => p.Version > targetVersion);
|
var packsToInstall = scriptPacks.Where(p => p.Version > targetVersion);
|
||||||
|
@ -90,7 +59,9 @@ namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
|
|
||||||
_logger.LogInformation($"Running script pack: '{pack.Version}'");
|
_logger.LogInformation($"Running script pack: '{pack.Version}'");
|
||||||
|
|
||||||
Array.ForEach(scripts, s => RunScript(s));
|
foreach (var script in scripts)
|
||||||
|
await RunScript(script);
|
||||||
|
|
||||||
var migratedVersion = new MigratedVersion() { Version = pack.Version.ToString(), Scripts = scripts.Select(z => Path.GetFileName(z)).ToArray() };
|
var migratedVersion = new MigratedVersion() { Version = pack.Version.ToString(), Scripts = scripts.Select(z => Path.GetFileName(z)).ToArray() };
|
||||||
migratedVersions.Add(migratedVersion);
|
migratedVersions.Add(migratedVersion);
|
||||||
}
|
}
|
||||||
|
@ -98,10 +69,7 @@ namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
signature.MigratedVersions = migratedVersions.ToArray();
|
signature.MigratedVersions = migratedVersions.ToArray();
|
||||||
signature.LastVersion = packsToInstall.OrderByDescending(z => z.Version).First().Version.ToString();
|
signature.LastVersion = packsToInstall.OrderByDescending(z => z.Version).First().Version.ToString();
|
||||||
|
|
||||||
var signatures = localSignatures != null ? new List<MigrationSignature>(localSignatures) : new List<MigrationSignature>();
|
await _migrationSignaturesService.SaveMigrationSignature(signature);
|
||||||
signatures.Add(signature);
|
|
||||||
|
|
||||||
SaveMigrationSignatures(signatures.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScriptPack[] GetScriptPacks()
|
private ScriptPack[] GetScriptPacks()
|
||||||
|
@ -112,10 +80,7 @@ namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
return packs.ToArray();
|
return packs.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunScript(string path)
|
private async Task RunScript(string path)
|
||||||
=> RunScriptAsync(path).GetAwaiter().GetResult();
|
|
||||||
|
|
||||||
private async Task RunScriptAsync(string path)
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Running sql script: '{path}'");
|
_logger.LogInformation($"Running sql script: '{path}'");
|
||||||
var sqlContent = File.ReadAllText(path);
|
var sqlContent = File.ReadAllText(path);
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Constants;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Extensions;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Models;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Repositories;
|
||||||
|
using NDB.Infrastructure.DatabaseMigration.Services.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace NDB.Infrastructure.DatabaseMigration.Services
|
||||||
|
{
|
||||||
|
internal class MigrationSignaturesService : IMigrationSignaturesService
|
||||||
|
{
|
||||||
|
private const string _migrationSignaturesFileName = "MigrationSignatures.xml";
|
||||||
|
private readonly string _migrationSignaturesFilePath;
|
||||||
|
private readonly ServiceConfiguration _configuration;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
private MigrationThumbprint Thumbprint;
|
||||||
|
|
||||||
|
public MigrationSignaturesService(ServiceConfiguration configuration, IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_migrationSignaturesFilePath = Path.Combine(configuration.Workspace, _migrationSignaturesFileName);
|
||||||
|
_configuration = configuration;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<MigrationSignature> GetLastMigrationSignature()
|
||||||
|
{
|
||||||
|
switch (_configuration.MetadataLocation)
|
||||||
|
{
|
||||||
|
case MetadataLocation.XmlFile:
|
||||||
|
return GetLastMigrationSignatureFromFile();
|
||||||
|
case MetadataLocation.Database:
|
||||||
|
return await GetLastMigrationSignatureFromDatabase();
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"Metadata location {_configuration.MetadataLocation} is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveMigrationSignature(MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
switch (_configuration.MetadataLocation)
|
||||||
|
{
|
||||||
|
case MetadataLocation.XmlFile:
|
||||||
|
SaveMigrationSignatureToFile(migrationSignature);
|
||||||
|
break;
|
||||||
|
case MetadataLocation.Database:
|
||||||
|
await SaveMigrationSignatureToDatabase(migrationSignature);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"Metadata location {_configuration.MetadataLocation} is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MigrationSignature GetLastMigrationSignatureFromFile()
|
||||||
|
{
|
||||||
|
Thumbprint = GetMigrationThumbprintFromFile();
|
||||||
|
var lastSignature = Thumbprint?.MigrationSignatures?.OrderByDescending(z => z.MigrationDate).FirstOrDefault();
|
||||||
|
return lastSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MigrationThumbprint GetMigrationThumbprintFromFile()
|
||||||
|
{
|
||||||
|
if (!File.Exists(_migrationSignaturesFilePath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var serializer = new XmlSerializer(typeof(MigrationThumbprint));
|
||||||
|
using (var reader = XmlReader.Create(_migrationSignaturesFilePath))
|
||||||
|
{
|
||||||
|
var migrationSignatureRoot = (MigrationThumbprint)serializer.Deserialize(reader);
|
||||||
|
return migrationSignatureRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveMigrationSignatureToFile(MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
if (Thumbprint != null)
|
||||||
|
{
|
||||||
|
var migrationSignatures = new List<MigrationSignature>(Thumbprint.MigrationSignatures) { migrationSignature };
|
||||||
|
Thumbprint.MigrationSignatures = migrationSignatures.ToArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Thumbprint = new MigrationThumbprint()
|
||||||
|
{
|
||||||
|
MigrationSignatures = new List<MigrationSignature>() { migrationSignature }.ToArray()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var serializer = new XmlSerializer(Thumbprint.GetType());
|
||||||
|
var settings = new XmlWriterSettings() { Indent = true };
|
||||||
|
using (var writer = XmlWriter.Create(_migrationSignaturesFilePath, settings))
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, Thumbprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<MigrationSignature> GetLastMigrationSignatureFromDatabase()
|
||||||
|
{
|
||||||
|
using (var scope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var _repository = scope.ServiceProvider.GetRequiredService<IMigrationRepository>();
|
||||||
|
var lastMigrationSignature = await _repository.GetLastMigrationSignature();
|
||||||
|
if (lastMigrationSignature == null)
|
||||||
|
return null;
|
||||||
|
return lastMigrationSignature.ToModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveMigrationSignatureToDatabase(MigrationSignature migrationSignature)
|
||||||
|
{
|
||||||
|
using (var scope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
var _repository = scope.ServiceProvider.GetRequiredService<IMigrationRepository>();
|
||||||
|
await _repository.AddMigrationSignature(migrationSignature.ToEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue