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);
}
}
}
}