From 1fbbee14e4c000931a8b404bac13b4ce376ab5a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Oct 2017 19:41:16 +0900 Subject: [PATCH] Allow migration from sqlite-net to EF Bonus stage --- osu.Game/Database/DatabaseContextFactory.cs | 2 +- osu.Game/Database/OsuDbContext.cs | 69 +++++++++++++++++++++ osu.Game/OsuGameBase.cs | 3 +- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index e22301adfe..359188b4e2 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -14,6 +14,6 @@ namespace osu.Game.Database this.host = host; } - public OsuDbContext GetContext() => new OsuDbContext(host.Storage.GetDatabaseConnectionString(@"client-ef")); + public OsuDbContext GetContext() => new OsuDbContext(host.Storage.GetDatabaseConnectionString(@"client")); } } diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 2938a8e7be..3f51ac1910 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -156,5 +156,74 @@ namespace osu.Game.Database public IDisposable BeginScope(TState state) => null; } } + + public void Migrate() + { + migrateFromSqliteNet(); + Database.Migrate(); + } + + private void migrateFromSqliteNet() + { + try + { + // will fail if EF hasn't touched the database yet. + Database.ExecuteSqlCommand("SELECT * FROM __EFMigrationsHistory LIMIT 1"); + } + catch + { + try + { + // will fail (intentionally) if we don't have sqlite-net data present. + Database.ExecuteSqlCommand("SELECT OnlineBeatmapSetId FROM BeatmapMetadata LIMIT 1"); + + // we are good to perform messy migration of data!. + Database.ExecuteSqlCommand("ALTER TABLE BeatmapDifficulty RENAME TO BeatmapDifficulty_Old"); + Database.ExecuteSqlCommand("ALTER TABLE BeatmapMetadata RENAME TO BeatmapMetadata_Old"); + Database.ExecuteSqlCommand("ALTER TABLE FileInfo RENAME TO FileInfo_Old"); + Database.ExecuteSqlCommand("ALTER TABLE KeyBinding RENAME TO KeyBinding_Old"); + Database.ExecuteSqlCommand("ALTER TABLE BeatmapSetInfo RENAME TO BeatmapSetInfo_Old"); + Database.ExecuteSqlCommand("ALTER TABLE BeatmapInfo RENAME TO BeatmapInfo_Old"); + Database.ExecuteSqlCommand("ALTER TABLE BeatmapSetFileInfo RENAME TO BeatmapSetFileInfo_Old"); + Database.ExecuteSqlCommand("ALTER TABLE RulesetInfo RENAME TO RulesetInfo_Old"); + + Database.ExecuteSqlCommand("DROP TABLE StoreVersion"); + + // perform EF migrations to create sane table structure. + Database.Migrate(); + + // copy data table by table to new structure, dropping old tables as we go. + Database.ExecuteSqlCommand("INSERT INTO FileInfo SELECT * FROM FileInfo_Old"); + Database.ExecuteSqlCommand("DROP TABLE FileInfo_Old"); + + Database.ExecuteSqlCommand("INSERT INTO KeyBinding SELECT ID, [Action], Keys, RulesetID, Variant FROM KeyBinding_Old"); + Database.ExecuteSqlCommand("DROP TABLE KeyBinding_Old"); + + Database.ExecuteSqlCommand( + "INSERT INTO BeatmapMetadata SELECT ID, Artist, ArtistUnicode, AudioFile, Author, BackgroundFile, PreviewTime, Source, Tags, Title, TitleUnicode FROM BeatmapMetadata_Old"); + Database.ExecuteSqlCommand("DROP TABLE BeatmapMetadata_Old"); + + Database.ExecuteSqlCommand( + "INSERT INTO BeatmapDifficulty SELECT `ID`, `ApproachRate`, `CircleSize`, `DrainRate`, `OverallDifficulty`, `SliderMultiplier`, `SliderTickRate` FROM BeatmapDifficulty_Old"); + Database.ExecuteSqlCommand("DROP TABLE BeatmapDifficulty_Old"); + + Database.ExecuteSqlCommand("INSERT INTO BeatmapSetInfo SELECT ID, DeletePending, Hash, BeatmapMetadataID, OnlineBeatmapSetID, Protected FROM BeatmapSetInfo_Old"); + Database.ExecuteSqlCommand("DROP TABLE BeatmapSetInfo_Old"); + + Database.ExecuteSqlCommand("INSERT INTO BeatmapSetFileInfo SELECT ID, BeatmapSetInfoID, FileInfoID, Filename FROM BeatmapSetFileInfo_Old"); + Database.ExecuteSqlCommand("DROP TABLE BeatmapSetFileInfo_Old"); + + Database.ExecuteSqlCommand("INSERT INTO RulesetInfo SELECT ID, Available, InstantiationInfo, Name FROM RulesetInfo_Old"); + Database.ExecuteSqlCommand("DROP TABLE RulesetInfo_Old"); + + Database.ExecuteSqlCommand( + "INSERT INTO BeatmapInfo SELECT ID, AudioLeadIn, BaseDifficultyID, BeatDivisor, BeatmapSetInfoID, Countdown, DistanceSpacing, GridSize, Hash, Hidden, LetterboxInBreaks, MD5Hash, NULLIF(BeatmapMetadataID, 0), OnlineBeatmapID, Path, RulesetID, SpecialStyle, StackLeniency, StarDifficulty, StoredBookmarks, TimelineZoom, Version, WidescreenStoryboard FROM BeatmapInfo_Old"); + Database.ExecuteSqlCommand("DROP TABLE BeatmapInfo_Old"); + } + catch + { + } + } + } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 22eb75fcea..be12f3ddbc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Reflection; -using Microsoft.EntityFrameworkCore; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Development; @@ -92,7 +91,7 @@ namespace osu.Game dependencies.Cache(LocalConfig); using (var context = contextFactory.GetContext()) - context.Database.Migrate(); + context.Migrate(); dependencies.Cache(API = new APIAccess {