diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 44776bb2a8..66552c43e0 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -155,8 +155,23 @@ private void load() dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); + + // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() + dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Host.Storage, contextFactory, Host)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap)); - dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host)); + + // this should likely be moved to ArchiveModelManager when another case appers where it is necessary + // to have inter-dependent model managers. this could be obtained with an IHasForeign interface to + // allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete. + List getBeatmapScores(BeatmapSetInfo set) + { + var beatmapIds = BeatmapManager.QueryBeatmaps(b => b.BeatmapSetInfoID == set.ID).Select(b => b.ID).ToList(); + return ScoreManager.QueryScores(s => beatmapIds.Contains(s.Beatmap.ID)).ToList(); + } + + BeatmapManager.ItemRemoved += i => ScoreManager.Delete(getBeatmapScores(i), true); + BeatmapManager.ItemAdded += (i, existing) => ScoreManager.Undelete(getBeatmapScores(i), true); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 7a527bfc69..6b737dc734 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -25,9 +25,9 @@ public class ScoreManager : ArchiveModelManager protected override string ImportFromStablePath => "Replays"; private readonly RulesetStore rulesets; - private readonly BeatmapManager beatmaps; + private readonly Func beatmaps; - public ScoreManager(RulesetStore rulesets, BeatmapManager beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) + public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, IDatabaseContextFactory contextFactory, IIpcHost importHost = null) : base(storage, contextFactory, new ScoreStore(contextFactory, storage), importHost) { this.rulesets = rulesets; @@ -43,7 +43,7 @@ protected override ScoreInfo CreateModel(ArchiveReader archive) { try { - return new DatabasedLegacyScoreParser(rulesets, beatmaps).Parse(stream).ScoreInfo; + return new DatabasedLegacyScoreParser(rulesets, beatmaps()).Parse(stream).ScoreInfo; } catch (LegacyScoreParser.BeatmapNotFoundException e) { @@ -53,7 +53,7 @@ protected override ScoreInfo CreateModel(ArchiveReader archive) } } - public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps, Files.Store); + public Score GetScore(ScoreInfo score) => new LegacyDatabasedScore(score, rulesets, beatmaps(), Files.Store); public List GetAllUsableScores() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList();