fix app startup with mysql (#2205)
* don't run pragma command on mysql * add not required pathhash * make media file path hash required * update changelog
This commit is contained in:
@@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Fixed
|
||||||
|
- Fix app startup with MySql/MariaDB
|
||||||
|
|
||||||
## [25.3.1] - 2025-07-24
|
## [25.3.1] - 2025-07-24
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -136,7 +136,9 @@ public class GetTroubleshootingInfoHandler : IRequestHandler<GetTroubleshootingI
|
|||||||
{
|
{
|
||||||
if (key.StartsWith("ETV_", StringComparison.OrdinalIgnoreCase)
|
if (key.StartsWith("ETV_", StringComparison.OrdinalIgnoreCase)
|
||||||
|| key.StartsWith("DOTNET_", StringComparison.OrdinalIgnoreCase)
|
|| key.StartsWith("DOTNET_", StringComparison.OrdinalIgnoreCase)
|
||||||
|| key.StartsWith("ASPNETCORE_", StringComparison.OrdinalIgnoreCase))
|
|| key.StartsWith("ASPNETCORE_", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| key.Equals("PROVIDER", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| key.StartsWith("ELASTICSEARCH", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
environment[key] = value;
|
environment[key] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ public class MediaFile
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public string PathHash { get; set; }
|
||||||
|
|
||||||
public int MediaVersionId { get; set; }
|
public int MediaVersionId { get; set; }
|
||||||
public MediaVersion MediaVersion { get; set; }
|
public MediaVersion MediaVersion { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Core;
|
||||||
|
|
||||||
|
public static class PathUtils
|
||||||
|
{
|
||||||
|
public static string GetPathHash(string path)
|
||||||
|
{
|
||||||
|
byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(path));
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
foreach (byte b in bytes)
|
||||||
|
{
|
||||||
|
builder.Append(b.ToString("x2", CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||||||
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(TvContext))]
|
[DbContext(typeof(TvContext))]
|
||||||
[Migration("20250723030616_Update_MediaFilePath")]
|
[Migration("20250726155754_Add_MediaFilePathHash")]
|
||||||
partial class Update_MediaFilePath
|
partial class Add_MediaFilePathHash
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@@ -1116,15 +1116,15 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
|||||||
b.Property<string>("Path")
|
b.Property<string>("Path")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PathHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("LibraryFolderId");
|
b.HasIndex("LibraryFolderId");
|
||||||
|
|
||||||
b.HasIndex("MediaVersionId");
|
b.HasIndex("MediaVersionId");
|
||||||
|
|
||||||
b.HasIndex("Path")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("MediaFile", (string)null);
|
b.ToTable("MediaFile", (string)null);
|
||||||
|
|
||||||
b.UseTptMappingStrategy();
|
b.UseTptMappingStrategy();
|
||||||
+22
-1
@@ -5,11 +5,15 @@
|
|||||||
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class Update_MediaFilePath : Migration
|
public partial class Add_MediaFilePathHash : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_MediaFile_Path",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<string>(
|
migrationBuilder.AlterColumn<string>(
|
||||||
name: "Path",
|
name: "Path",
|
||||||
table: "MediaFile",
|
table: "MediaFile",
|
||||||
@@ -20,11 +24,22 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
|||||||
oldNullable: true)
|
oldNullable: true)
|
||||||
.Annotation("MySql:CharSet", "utf8mb4")
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<string>(
|
migrationBuilder.AlterColumn<string>(
|
||||||
name: "Path",
|
name: "Path",
|
||||||
table: "MediaFile",
|
table: "MediaFile",
|
||||||
@@ -35,6 +50,12 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
|||||||
oldNullable: true)
|
oldNullable: true)
|
||||||
.Annotation("MySql:CharSet", "utf8mb4")
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MediaFile_Path",
|
||||||
|
table: "MediaFile",
|
||||||
|
column: "Path",
|
||||||
|
unique: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+6145
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Update_MediaFilePathHash : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.UpdateData(
|
||||||
|
table: "MediaFile",
|
||||||
|
keyColumn: "PathHash",
|
||||||
|
keyValue: null,
|
||||||
|
column: "PathHash",
|
||||||
|
value: "");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "varchar(255)",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "longtext",
|
||||||
|
oldNullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MediaFile_PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
column: "PathHash",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_MediaFile_PathHash",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "varchar(255)")
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1113,13 +1113,17 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
|||||||
b.Property<string>("Path")
|
b.Property<string>("Path")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PathHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("LibraryFolderId");
|
b.HasIndex("LibraryFolderId");
|
||||||
|
|
||||||
b.HasIndex("MediaVersionId");
|
b.HasIndex("MediaVersionId");
|
||||||
|
|
||||||
b.HasIndex("Path")
|
b.HasIndex("PathHash")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("MediaFile", (string)null);
|
b.ToTable("MediaFile", (string)null);
|
||||||
|
|||||||
Generated
+5978
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Add_MediaFilePathHash : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_MediaFile_Path",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MediaFile_Path",
|
||||||
|
table: "MediaFile",
|
||||||
|
column: "Path",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+5982
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Update_MediaFilePathHash : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "TEXT",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MediaFile_PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
column: "PathHash",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_MediaFile_PathHash",
|
||||||
|
table: "MediaFile");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "PathHash",
|
||||||
|
table: "MediaFile",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "TEXT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1056,13 +1056,17 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
|||||||
b.Property<string>("Path")
|
b.Property<string>("Path")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PathHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("LibraryFolderId");
|
b.HasIndex("LibraryFolderId");
|
||||||
|
|
||||||
b.HasIndex("MediaVersionId");
|
b.HasIndex("MediaVersionId");
|
||||||
|
|
||||||
b.HasIndex("Path")
|
b.HasIndex("PathHash")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("MediaFile", (string)null);
|
b.ToTable("MediaFile", (string)null);
|
||||||
|
|||||||
@@ -10,9 +10,12 @@ public class MediaFileConfiguration : IEntityTypeConfiguration<MediaFile>
|
|||||||
{
|
{
|
||||||
builder.ToTable("MediaFile");
|
builder.ToTable("MediaFile");
|
||||||
|
|
||||||
builder.HasIndex(f => f.Path)
|
builder.HasIndex(f => f.PathHash)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
|
builder.Property(f => f.PathHash)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
builder.HasOne(f => f.LibraryFolder)
|
builder.HasOne(f => f.LibraryFolder)
|
||||||
.WithMany(f => f.MediaFiles)
|
.WithMany(f => f.MediaFiles)
|
||||||
.HasForeignKey(f => f.LibraryFolderId)
|
.HasForeignKey(f => f.LibraryFolderId)
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ public static class DbInitializer
|
|||||||
{
|
{
|
||||||
public static async Task<Unit> Initialize(TvContext context, CancellationToken cancellationToken)
|
public static async Task<Unit> Initialize(TvContext context, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await context.Connection.ExecuteAsync("PRAGMA journal_mode=WAL", cancellationToken);
|
if (TvContext.IsSqlite)
|
||||||
|
{
|
||||||
|
await context.Connection.ExecuteAsync("PRAGMA journal_mode=WAL", cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (!context.LanguageCodes.Any())
|
if (!context.LanguageCodes.Any())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public class ImageRepository : IImageRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ public class MovieRepository : IMovieRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ public class MusicVideoRepository : IMusicVideoRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ public class OtherVideoRepository : IOtherVideoRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public class RemoteStreamRepository(
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public class SongRepository : ISongRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -773,7 +773,7 @@ public class TelevisionRepository : ITelevisionRepository
|
|||||||
[
|
[
|
||||||
new MediaVersion
|
new MediaVersion
|
||||||
{
|
{
|
||||||
MediaFiles = [new MediaFile { Path = path, LibraryFolderId = libraryFolderId }],
|
MediaFiles = [new MediaFile { Path = path, PathHash = PathUtils.GetPathHash(path), LibraryFolderId = libraryFolderId }],
|
||||||
Streams = []
|
Streams = []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class TvContext : DbContext
|
|||||||
|
|
||||||
public static string LastInsertedRowId { get; set; } = "last_insert_rowid()";
|
public static string LastInsertedRowId { get; set; } = "last_insert_rowid()";
|
||||||
public static string CaseInsensitiveCollation { get; set; } = "NOCASE";
|
public static string CaseInsensitiveCollation { get; set; } = "NOCASE";
|
||||||
|
public static bool IsSqlite { get; set; }
|
||||||
|
|
||||||
public IDbConnection Connection => Database.GetDbConnection();
|
public IDbConnection Connection => Database.GetDbConnection();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using ErsatzTV.Core;
|
using Dapper;
|
||||||
|
using ErsatzTV.Core;
|
||||||
using ErsatzTV.Infrastructure.Data;
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace ErsatzTV.Services.RunOnce;
|
namespace ErsatzTV.Services.RunOnce;
|
||||||
@@ -28,11 +30,39 @@ public class DatabaseMigratorService : BackgroundService
|
|||||||
|
|
||||||
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
||||||
await using TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
|
await using TvContext dbContext = scope.ServiceProvider.GetRequiredService<TvContext>();
|
||||||
|
|
||||||
|
await dbContext.Database.MigrateAsync("Add_MediaFilePathHash", stoppingToken);
|
||||||
|
|
||||||
|
// this can't be part of a migration, so we have to stop here and run some sql
|
||||||
|
await PopulatePathHashes(dbContext);
|
||||||
|
|
||||||
|
// then continue migrating
|
||||||
await dbContext.Database.MigrateAsync(stoppingToken);
|
await dbContext.Database.MigrateAsync(stoppingToken);
|
||||||
|
|
||||||
await DbInitializer.Initialize(dbContext, stoppingToken);
|
await DbInitializer.Initialize(dbContext, stoppingToken);
|
||||||
|
|
||||||
_systemStartup.DatabaseIsReady();
|
_systemStartup.DatabaseIsReady();
|
||||||
|
|
||||||
_logger.LogInformation("Done applying database migrations");
|
_logger.LogInformation("Done applying database migrations");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task PopulatePathHashes(TvContext dbContext)
|
||||||
|
{
|
||||||
|
if (await dbContext.Connection.ExecuteScalarAsync<int>(
|
||||||
|
"SELECT COUNT(*) FROM `MediaFile` WHERE `PathHash` IS NULL OR `PathHash` = ''") == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbContext.Connection is SqliteConnection sqliteConnection)
|
||||||
|
{
|
||||||
|
sqliteConnection.CreateFunction("HASH_SHA256", (string text) => PathUtils.GetPathHash(text));
|
||||||
|
await dbContext.Connection.ExecuteAsync("UPDATE `MediaFile` SET `PathHash` = HASH_SHA256(`Path`);");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mysql
|
||||||
|
await dbContext.Connection.ExecuteAsync("UPDATE `MediaFile` SET `PathHash` = sha2(`Path`, 256);");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,8 @@ public class Startup
|
|||||||
{
|
{
|
||||||
if (databaseProvider == Provider.Sqlite.Name)
|
if (databaseProvider == Provider.Sqlite.Name)
|
||||||
{
|
{
|
||||||
|
TvContext.IsSqlite = true;
|
||||||
|
|
||||||
options.UseSqlite(
|
options.UseSqlite(
|
||||||
sqliteConnectionString,
|
sqliteConnectionString,
|
||||||
o =>
|
o =>
|
||||||
@@ -373,6 +375,8 @@ public class Startup
|
|||||||
|
|
||||||
if (databaseProvider == Provider.MySql.Name)
|
if (databaseProvider == Provider.MySql.Name)
|
||||||
{
|
{
|
||||||
|
TvContext.IsSqlite = false;
|
||||||
|
|
||||||
options.UseMySql(
|
options.UseMySql(
|
||||||
mySqlConnectionString,
|
mySqlConnectionString,
|
||||||
ServerVersion.AutoDetect(mySqlConnectionString),
|
ServerVersion.AutoDetect(mySqlConnectionString),
|
||||||
|
|||||||
Reference in New Issue
Block a user