1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-20 05:25:36 +08:00

Add proper handling for OnlineBeatmapSetID conflicts

Not yet working
This commit is contained in:
Dean Herbert 2018-02-09 21:31:33 +09:00
parent a1513351c0
commit 721bb7e4dd
3 changed files with 69 additions and 4 deletions

View File

@ -87,6 +87,40 @@ namespace osu.Game.Tests.Beatmaps.IO
}
}
[Test]
public void TestImportThenImportDifferentHash()
{
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImportDifferentHash"))
{
try
{
var osu = loadOsu(host);
var manager = osu.Dependencies.Get<BeatmapManager>();
var imported = loadOszIntoOsu(osu);
//var change = manager.QueryBeatmapSets(_ => true).First();
imported.Hash += "-changed";
manager.Update(imported);
var importedSecondTime = loadOszIntoOsu(osu);
// check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
Assert.IsTrue(imported.ID == importedSecondTime.ID);
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 1);
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1);
}
finally
{
host.Exit();
}
}
}
[Test]
public void TestImportThenDeleteThenImport()
{

View File

@ -210,7 +210,12 @@ namespace osu.Game.Beatmaps
{
var existingOnlineId = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID);
if (existingOnlineId != null)
{
// {Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962…}
Delete(existingOnlineId);
beatmaps.Cleanup(s => s.ID == existingOnlineId.ID);
}
}
beatmapSet.Files = createFileInfos(archive, getFileStoreWithContext(context));
@ -332,6 +337,12 @@ namespace osu.Game.Beatmaps
/// <returns>The <see cref="DownloadBeatmapSetRequest"/> object if it exists, or null.</returns>
public DownloadBeatmapSetRequest GetExistingDownload(BeatmapSetInfo beatmap) => currentDownloads.Find(d => d.BeatmapSet.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID);
/// <summary>
/// Update a BeatmapSetInfo with all changes. TODO: This only supports very basic updates currently.
/// </summary>
/// <param name="beatmapSet">The beatmap set to update.</param>
public void Update(BeatmapSetInfo beatmap) => beatmaps.Update(beatmap);
/// <summary>
/// Delete a beatmap from the manager.
/// Is a no-op for already deleted beatmaps.

View File

@ -3,6 +3,7 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using osu.Game.Database;
@ -50,6 +51,22 @@ namespace osu.Game.Beatmaps
BeatmapSetAdded?.Invoke(beatmapSet);
}
/// <summary>
/// Update a <see cref="BeatmapSetInfo"/> in the database. TODO: This only supports very basic updates currently.
/// </summary>
/// <param name="beatmapSet">The beatmap to update.</param>
public void Update(BeatmapSetInfo beatmapSet)
{
BeatmapSetRemoved?.Invoke(beatmapSet);
var context = GetContext();
context.BeatmapSetInfo.Update(beatmapSet);
context.SaveChanges();
BeatmapSetAdded?.Invoke(beatmapSet);
}
/// <summary>
/// Delete a <see cref="BeatmapSetInfo"/> from the database.
/// </summary>
@ -126,14 +143,17 @@ namespace osu.Game.Beatmaps
return true;
}
public override void Cleanup()
public override void Cleanup() => Cleanup(_ => true);
public void Cleanup(Expression<Func<BeatmapSetInfo, bool>> query)
{
var context = GetContext();
var purgeable = context.BeatmapSetInfo.Where(s => s.DeletePending && !s.Protected)
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
.Include(s => s.Metadata);
.Where(query)
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
.Include(s => s.Metadata);
// metadata is M-N so we can't rely on cascades
context.BeatmapMetadata.RemoveRange(purgeable.Select(s => s.Metadata));