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 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(Thumbprint.MigrationSignatures) { migrationSignature }; Thumbprint.MigrationSignatures = migrationSignatures.ToArray(); } else { Thumbprint = new MigrationThumbprint() { MigrationSignatures = new List() { 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 GetLastMigrationSignatureFromDatabase() { using (var scope = _serviceProvider.CreateScope()) { var _repository = scope.ServiceProvider.GetRequiredService(); 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(); await _repository.AddMigrationSignature(migrationSignature.ToEntity()); } } } }