using System; using System.Collections.Immutable; using System.IO; using System.Linq; using Emby.Server.Implementations.Data; using Jellyfin.Data.Entities; using Jellyfin.Server.Implementations; using MediaBrowser.Controller; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Migrations.Routines; /// /// The migration routine for migrating the userdata database to EF Core. /// public class MigrateUserData : IMigrationRoutine { private const string DbFilename = "library.db"; private readonly ILogger _logger; private readonly IServerApplicationPaths _paths; private readonly IDbContextFactory _provider; /// /// Initializes a new instance of the class. /// /// The logger. /// The database provider. /// The server application paths. public MigrateUserData( ILogger logger, IDbContextFactory provider, IServerApplicationPaths paths) { _logger = logger; _provider = provider; _paths = paths; } /// public Guid Id => Guid.Parse("5bcb4197-e7c0-45aa-9902-963bceab5798"); /// public string Name => "MigrateUserData"; /// public bool PerformOnNewInstall => false; /// public void Perform() { _logger.LogInformation("Migrating the userdata from library.db may take a while, do not stop Jellyfin."); var dataPath = _paths.DataPath; using var connection = new SqliteConnection($"Filename={Path.Combine(dataPath, DbFilename)}"); connection.Open(); using var dbContext = _provider.CreateDbContext(); var queryResult = connection.Query("SELECT key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex FROM UserDatas"); dbContext.UserData.ExecuteDelete(); var users = dbContext.Users.AsNoTracking().ToImmutableArray(); foreach (SqliteDataReader dto in queryResult) { var entity = new UserData() { Key = dto.GetString(0), UserId = users.ElementAt(dto.GetInt32(1)).Id, Rating = dto.IsDBNull(2) ? null : dto.GetDouble(2), Played = dto.GetBoolean(3), PlayCount = dto.GetInt32(4), IsFavorite = dto.GetBoolean(5), PlaybackPositionTicks = dto.GetInt64(6), LastPlayedDate = dto.IsDBNull(7) ? null : dto.GetDateTime(7), AudioStreamIndex = dto.IsDBNull(8) ? null : dto.GetInt32(8), SubtitleStreamIndex = dto.IsDBNull(9) ? null : dto.GetInt32(9), }; dbContext.UserData.Add(entity); } dbContext.SaveChanges(); } }