2021-03-15 11:42:41 +08:00
|
|
|
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
|
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
|
|
2021-03-15 11:47:58 +08:00
|
|
|
|
using System;
|
2021-03-15 11:42:41 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using osu.Game.Beatmaps;
|
|
|
|
|
using osu.Game.Scoring;
|
2021-03-15 11:47:58 +08:00
|
|
|
|
using osu.Game.Skinning;
|
2021-03-15 11:42:41 +08:00
|
|
|
|
|
|
|
|
|
namespace osu.Game.Database
|
|
|
|
|
{
|
2021-03-15 11:47:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Extension methods which contain workarounds to make EFcore 5.x work with our existing (incorrect) thread safety.
|
|
|
|
|
/// The intention is to avoid blocking package updates while we consider the future of the database backend, with a potential backend switch imminent.
|
|
|
|
|
/// </summary>
|
2021-03-15 11:42:41 +08:00
|
|
|
|
public static class DatabaseWorkaroundExtensions
|
|
|
|
|
{
|
2021-03-15 11:47:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Re-query the provided model to ensure it is in a sane state. This method requires explicit implementation per model type.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="model"></param>
|
|
|
|
|
/// <param name="contextFactory"></param>
|
2021-03-15 11:42:41 +08:00
|
|
|
|
public static void Requery(this IHasPrimaryKey model, IDatabaseContextFactory contextFactory)
|
|
|
|
|
{
|
|
|
|
|
switch (model)
|
|
|
|
|
{
|
2021-03-15 11:47:58 +08:00
|
|
|
|
case SkinInfo skinInfo:
|
|
|
|
|
requeryFiles(skinInfo.Files, contextFactory);
|
|
|
|
|
break;
|
|
|
|
|
|
2021-03-15 11:42:41 +08:00
|
|
|
|
case ScoreInfo scoreInfo:
|
2021-03-15 13:20:59 +08:00
|
|
|
|
requeryFiles(scoreInfo.Beatmap.BeatmapSet.Files, contextFactory);
|
2021-03-15 11:47:58 +08:00
|
|
|
|
requeryFiles(scoreInfo.Files, contextFactory);
|
2021-03-15 11:42:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BeatmapSetInfo beatmapSetInfo:
|
|
|
|
|
var context = contextFactory.Get();
|
|
|
|
|
|
|
|
|
|
foreach (var beatmap in beatmapSetInfo.Beatmaps)
|
|
|
|
|
{
|
|
|
|
|
// Workaround System.InvalidOperationException
|
|
|
|
|
// The instance of entity type 'RulesetInfo' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked.
|
|
|
|
|
beatmap.Ruleset = context.RulesetInfo.Find(beatmap.RulesetID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
requeryFiles(beatmapSetInfo.Files, contextFactory);
|
|
|
|
|
break;
|
2021-03-15 11:48:23 +08:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException($"{nameof(Requery)} does not have support for the provided model type", nameof(model));
|
2021-03-15 11:42:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-15 12:26:14 +08:00
|
|
|
|
void requeryFiles<T>(List<T> files, IDatabaseContextFactory databaseContextFactory) where T : class, INamedFileInfo
|
2021-03-15 11:42:41 +08:00
|
|
|
|
{
|
2021-03-15 12:26:14 +08:00
|
|
|
|
var dbContext = databaseContextFactory.Get();
|
|
|
|
|
|
|
|
|
|
foreach (var file in files)
|
|
|
|
|
{
|
|
|
|
|
Requery(file, dbContext);
|
|
|
|
|
}
|
2021-03-15 11:42:41 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-15 12:26:14 +08:00
|
|
|
|
|
|
|
|
|
public static void Requery(this INamedFileInfo file, OsuDbContext dbContext)
|
|
|
|
|
{
|
|
|
|
|
// Workaround System.InvalidOperationException
|
|
|
|
|
// The instance of entity type 'FileInfo' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked.
|
|
|
|
|
file.FileInfo = dbContext.FileInfo.Find(file.FileInfoID);
|
|
|
|
|
}
|
2021-03-15 11:42:41 +08:00
|
|
|
|
}
|
|
|
|
|
}
|