// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using osu.Game.Database; namespace osu.Game.Beatmaps { /// /// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing /// public class BeatmapStore : DatabaseBackedStore { public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; public event Action BeatmapHidden; public event Action BeatmapRestored; public BeatmapStore(OsuDbContext connection) : base(connection) { } protected override void Prepare(bool reset = false) { if (reset) { // https://stackoverflow.com/a/10450893 Connection.Database.ExecuteSqlCommand("DELETE FROM BeatmapMetadata"); Connection.Database.ExecuteSqlCommand("DELETE FROM BeatmapDifficulty"); Connection.Database.ExecuteSqlCommand("DELETE FROM BeatmapSetInfo"); Connection.Database.ExecuteSqlCommand("DELETE FROM BeatmapSetFileInfo"); Connection.Database.ExecuteSqlCommand("DELETE FROM BeatmapInfo"); } } protected override void StartupTasks() { base.StartupTasks(); cleanupPendingDeletions(); } /// /// Add a to the database. /// /// The beatmap to add. public void Add(BeatmapSetInfo beatmapSet) { Connection.BeatmapSetInfo.Update(beatmapSet); Connection.SaveChanges(); BeatmapSetAdded?.Invoke(beatmapSet); } /// /// Delete a from the database. /// /// The beatmap to delete. /// Whether the beatmap's was changed. public bool Delete(BeatmapSetInfo beatmapSet) { if (beatmapSet.DeletePending) return false; beatmapSet.DeletePending = true; Connection.BeatmapSetInfo.Remove(beatmapSet); Connection.SaveChanges(); BeatmapSetRemoved?.Invoke(beatmapSet); return true; } /// /// Restore a previously deleted . /// /// The beatmap to restore. /// Whether the beatmap's was changed. public bool Undelete(BeatmapSetInfo beatmapSet) { if (!beatmapSet.DeletePending) return false; beatmapSet.DeletePending = false; Connection.BeatmapSetInfo.Update(beatmapSet); BeatmapSetAdded?.Invoke(beatmapSet); return true; } /// /// Hide a in the database. /// /// The beatmap to hide. /// Whether the beatmap's was changed. public bool Hide(BeatmapInfo beatmap) { if (beatmap.Hidden) return false; beatmap.Hidden = true; Connection.BeatmapInfo.Update(beatmap); BeatmapHidden?.Invoke(beatmap); return true; } /// /// Restore a previously hidden . /// /// The beatmap to restore. /// Whether the beatmap's was changed. public bool Restore(BeatmapInfo beatmap) { if (!beatmap.Hidden) return false; beatmap.Hidden = false; Connection.BeatmapInfo.Update(beatmap); BeatmapRestored?.Invoke(beatmap); return true; } private void cleanupPendingDeletions() { Connection.BeatmapSetInfo.RemoveRange(Connection.BeatmapSetInfo.Where(b => b.DeletePending && !b.Protected)); } public BeatmapSetInfo QueryBeatmapSet(Func query) { return Connection.BeatmapSetInfo .Include(b => b.Metadata) .Include(b => b.Beatmaps).ThenInclude(b => b.Ruleset) .Include(b => b.Beatmaps).ThenInclude(b => b.Difficulty) .Include(b => b.Files).ThenInclude(f => f.FileInfo) .FirstOrDefault(query); } public List QueryBeatmapSets(Expression> query) { return Connection.BeatmapSetInfo .Include(b => b.Metadata) .Include(b => b.Beatmaps).ThenInclude(b => b.Ruleset) .Include(b => b.Beatmaps).ThenInclude(b => b.Difficulty) .Include(b => b.Files).ThenInclude(f => f.FileInfo) .Where(query).ToList(); } public BeatmapInfo QueryBeatmap(Func query) { return Connection.BeatmapInfo .Include(b => b.BeatmapSet) .Include(b => b.Metadata) .Include(b => b.Ruleset) .Include(b => b.Difficulty) .FirstOrDefault(query); } public List QueryBeatmaps(Expression> query) { return Connection.BeatmapInfo .Include(b => b.BeatmapSet) .Include(b => b.Metadata) .Include(b => b.Ruleset) .Include(b => b.Difficulty) .Where(query).ToList(); } } }