using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using osu.Framework.Platform; namespace osu.Game.Database { /// /// A typed store which supports basic addition, deletion and updating for soft-deletable models. /// /// The databased model. public abstract class MutableDatabaseBackedStore : DatabaseBackedStore where T : class, IHasPrimaryKey, ISoftDelete { public event Action ItemAdded; public event Action ItemRemoved; protected MutableDatabaseBackedStore(IDatabaseContextFactory contextFactory, Storage storage = null) : base(contextFactory, storage) { } public void Add(T item) { using (var usage = ContextFactory.GetForWrite()) { var context = usage.Context; context.Attach(item); } ItemAdded?.Invoke(item); } /// /// Update a in the database. /// /// The item to update. public void Update(T item) { ItemRemoved?.Invoke(item); using (var usage = ContextFactory.GetForWrite()) usage.Context.Update(item); ItemAdded?.Invoke(item); } public bool Delete(T item) { using (ContextFactory.GetForWrite()) { Refresh(ref item); if (item.DeletePending) return false; item.DeletePending = true; } ItemRemoved?.Invoke(item); return true; } public bool Undelete(T item) { using (ContextFactory.GetForWrite()) { Refresh(ref item); if (!item.DeletePending) return false; item.DeletePending = false; } ItemAdded?.Invoke(item); return true; } protected virtual IQueryable AddIncludesForDeletion(IQueryable query) => query; protected virtual void Purge(List items, OsuDbContext context) { // cascades down to beatmaps. context.RemoveRange(items); } /// /// Purge items in a pending delete state. /// /// An optional query limiting the scope of the purge. public void PurgeDeletable(Expression> query = null) { using (var usage = ContextFactory.GetForWrite()) { var context = usage.Context; var lookup = context.Set().Where(s => s.DeletePending); if (query != null) lookup = lookup.Where(query); AddIncludesForDeletion(lookup); var purgeable = lookup.ToList(); if (!purgeable.Any()) return; Purge(purgeable, context); } } } }