diff --git a/API/Data/ManualMigrations/MigrateSeriesRelationsExport.cs b/API/Data/ManualMigrations/MigrateSeriesRelationsExport.cs deleted file mode 100644 index 4427a66877..0000000000 --- a/API/Data/ManualMigrations/MigrateSeriesRelationsExport.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using API.Entities.Enums; -using CsvHelper; -using Kavita.Common.EnvironmentInfo; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; - -namespace API.Data.ManualMigrations; - -internal sealed class SeriesRelationMigrationOutput -{ - public required string SeriesName { get; set; } - public int SeriesId { get; set; } - public required string TargetSeriesName { get; set; } - public int TargetId { get; set; } - public RelationKind Relationship { get; set; } -} - -/// -/// Introduced in v0.6.1.2 and v0.7, this exports to a temp file the existing series relationships. It is a 3 part migration. -/// This will run first, to export the data, then the DB migration will change the way the DB is constructed, then the last migration -/// will import said file and re-construct the relationships. -/// -public static class MigrateSeriesRelationsExport -{ - private const string OutputFile = "config/relations.csv"; - private const string CompleteOutputFile = "config/relations-imported.csv"; - public static async Task Migrate(DataContext dataContext, ILogger logger) - { - logger.LogCritical("Running MigrateSeriesRelationsExport migration - Please be patient, this may take some time. This is not an error"); - if (BuildInfo.Version > new Version(0, 6, 1, 3) - || new FileInfo(OutputFile).Exists - || new FileInfo(CompleteOutputFile).Exists) - { - logger.LogCritical("Running MigrateSeriesRelationsExport migration - complete. Nothing to do"); - return; - } - - var seriesWithRelationships = await dataContext.Series - .Where(s => s.Relations.Any()) - .Include(s => s.Relations) - .ThenInclude(r => r.TargetSeries) - .ToListAsync(); - - var records = new List(); - var excludedRelationships = new List() - { - RelationKind.Parent, - }; - foreach (var series in seriesWithRelationships) - { - foreach (var relationship in series.Relations.Where(r => !excludedRelationships.Contains(r.RelationKind))) - { - records.Add(new SeriesRelationMigrationOutput() - { - SeriesId = series.Id, - SeriesName = series.Name, - Relationship = relationship.RelationKind, - TargetId = relationship.TargetSeriesId, - TargetSeriesName = relationship.TargetSeries.Name - }); - } - } - - await using var writer = new StreamWriter(OutputFile); - await using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) - { - await csv.WriteRecordsAsync(records); - } - - await writer.DisposeAsync(); - - logger.LogCritical("{OutputFile} has a backup of all data", OutputFile); - - logger.LogCritical("Deleting all relationships in the DB. This is not an error"); - var entities = await dataContext.SeriesRelation - .Include(s => s.Series) - .Include(s => s.TargetSeries) - .Select(s => s) - .ToListAsync(); - - foreach (var seriesWithRelationship in entities) - { - logger.LogCritical("Deleting {SeriesName} --{RelationshipKind}--> {TargetSeriesName}", - seriesWithRelationship.Series.Name, seriesWithRelationship.RelationKind, seriesWithRelationship.TargetSeries.Name); - dataContext.SeriesRelation.Remove(seriesWithRelationship); - - await dataContext.SaveChangesAsync(); - } - - // In case of corrupted entities (where series were deleted but their Id still existed, we delete the rest of the table) - dataContext.SeriesRelation.RemoveRange(dataContext.SeriesRelation); - await dataContext.SaveChangesAsync(); - - - logger.LogCritical("Running MigrateSeriesRelationsExport migration - Completed. This is not an error"); - } -} diff --git a/API/Data/ManualMigrations/MigrateSeriesRelationsImport.cs b/API/Data/ManualMigrations/MigrateSeriesRelationsImport.cs deleted file mode 100644 index 9faefde6ad..0000000000 --- a/API/Data/ManualMigrations/MigrateSeriesRelationsImport.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using API.Entities.Metadata; -using CsvHelper; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; - -namespace API.Data.ManualMigrations; - -/// -/// Introduced in v0.6.1.2 and v0.7, this imports to a temp file the existing series relationships. It is a 3 part migration. -/// This will run last, to import the data and re-construct the relationships. -/// -public static class MigrateSeriesRelationsImport -{ - private const string OutputFile = "config/relations.csv"; - private const string CompleteOutputFile = "config/relations-imported.csv"; - public static async Task Migrate(DataContext dataContext, ILogger logger) - { - logger.LogCritical("Running MigrateSeriesRelationsImport migration - Please be patient, this may take some time. This is not an error"); - if (!new FileInfo(OutputFile).Exists) - { - logger.LogCritical("Running MigrateSeriesRelationsImport migration - complete. Nothing to do"); - return; - } - - logger.LogCritical("Loading backed up relationships into the DB"); - List records; - using var reader = new StreamReader(OutputFile); - using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) - { - records = csv.GetRecords().ToList(); - } - - foreach (var relation in records) - { - logger.LogCritical("Importing {SeriesName} --{RelationshipKind}--> {TargetSeriesName}", - relation.SeriesName, relation.Relationship, relation.TargetSeriesName); - - // Filter out series that don't exist - if (!await dataContext.Series.AnyAsync(s => s.Id == relation.SeriesId) || - !await dataContext.Series.AnyAsync(s => s.Id == relation.TargetId)) - continue; - - await dataContext.SeriesRelation.AddAsync(new SeriesRelation() - { - SeriesId = relation.SeriesId, - TargetSeriesId = relation.TargetId, - RelationKind = relation.Relationship - }); - - } - await dataContext.SaveChangesAsync(); - - File.Move(OutputFile, CompleteOutputFile); - - logger.LogCritical("Running MigrateSeriesRelationsImport migration - Completed. This is not an error"); - } -} diff --git a/API/Program.cs b/API/Program.cs index 78a4f5e075..625949f656 100644 --- a/API/Program.cs +++ b/API/Program.cs @@ -70,7 +70,8 @@ public static async Task Main(string[] args) var logger = services.GetRequiredService>(); var context = services.GetRequiredService(); var pendingMigrations = await context.Database.GetPendingMigrationsAsync(); - if (pendingMigrations.Any()) + var isDbCreated = await context.Database.CanConnectAsync(); + if (isDbCreated && pendingMigrations.Any()) { logger.LogInformation("Performing backup as migrations are needed. Backup will be kavita.db in temp folder"); var migrationDirectory = await GetMigrationDirectory(context, directoryService); @@ -84,16 +85,6 @@ public static async Task Main(string[] args) } } - // This must run before the migration - try - { - await MigrateSeriesRelationsExport.Migrate(context, logger); - } - catch (Exception) - { - // If fresh install, could fail and we should just carry on as it's not applicable - } - await context.Database.MigrateAsync(); await Seed.SeedRoles(services.GetRequiredService>()); diff --git a/openapi.json b/openapi.json index 623ed1b089..a6f6300e6f 100644 --- a/openapi.json +++ b/openapi.json @@ -7,7 +7,7 @@ "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "0.7.5.4" + "version": "0.7.5.5" }, "servers": [ {