diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 78042349d1..4ff16b604a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -91,7 +91,8 @@ namespace osu.Game.Beatmaps protected override void Populate(BeatmapSetInfo model, ArchiveReader archive) { - model.Beatmaps = createBeatmapDifficulties(archive); + if (archive != null) + model.Beatmaps = createBeatmapDifficulties(archive); foreach (BeatmapInfo b in model.Beatmaps) { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index cbf0df3227..0465c0ad73 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework.IO.File; using osu.Framework.Logging; @@ -175,7 +176,24 @@ namespace osu.Game.Database /// The archive to be imported. public TModel Import(ArchiveReader archive) { - TModel item = null; + try + { + return Import(CreateModel(archive), archive); + } + catch (Exception e) + { + Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database); + return null; + } + } + + /// + /// Import an item from a . + /// + /// The model to be imported. + /// An optional archive to use for model population. + public TModel Import(TModel item, ArchiveReader archive = null) + { delayEvents(); try @@ -186,18 +204,16 @@ namespace osu.Game.Database { if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - // create a new model (don't yet add to database) - item = CreateModel(archive); - var existing = CheckForExisting(item); if (existing != null) { - Logger.Log($"Found existing {typeof(TModel)} for {archive.Name} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); return existing; } - item.Files = createFileInfos(archive, Files); + if (archive != null) + item.Files = createFileInfos(archive, Files); Populate(item, archive); @@ -211,11 +227,11 @@ namespace osu.Game.Database } } - Logger.Log($"Import of {archive.Name} successfully completed!", LoggingTarget.Database); + Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); } catch (Exception e) { - Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database); + Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); item = null; } finally @@ -227,12 +243,6 @@ namespace osu.Game.Database return item; } - /// - /// Import an item from a . - /// - /// The model to be imported. - public void Import(TModel item) => ModelStore.Add(item); - /// /// Perform an update of the specified item. /// TODO: Support file changes. @@ -385,8 +395,8 @@ namespace osu.Game.Database /// After this method, the model should be in a state ready to commit to a store. /// /// The model to populate. - /// The archive to use as a reference for population. - protected virtual void Populate(TModel model, ArchiveReader archive) + /// The archive to use as a reference for population. May be null. + protected virtual void Populate(TModel model, [CanBeNull] ArchiveReader archive) { } diff --git a/osu.Game/Database/SingletonContextFactory.cs b/osu.Game/Database/SingletonContextFactory.cs index ce3fbf6881..a7158c0583 100644 --- a/osu.Game/Database/SingletonContextFactory.cs +++ b/osu.Game/Database/SingletonContextFactory.cs @@ -14,6 +14,6 @@ namespace osu.Game.Database public OsuDbContext Get() => context; - public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null); + public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null) { IsTransactionLeader = true }; } }