diff --git a/osu.Game/Database/Live.cs b/osu.Game/Database/Live.cs index 7d607a4637..f4882ae325 100644 --- a/osu.Game/Database/Live.cs +++ b/osu.Game/Database/Live.cs @@ -14,7 +14,7 @@ namespace osu.Game.Database /// /// /// To consume this as a live instance, the live object should be stored and accessed via each time. - /// To consume this as a detached instance, assign to a variable of type . The implicit conversion will handle detaching an instance. + /// To consume this as a detached instance, assign to a variable of type . The implicit conversion will handle detaching an instance. /// /// The underlying object type. Should be a with a primary key provided via . public class Live : IEquatable>, IHasGuidPrimaryKey @@ -33,24 +33,34 @@ namespace osu.Game.Database private readonly ThreadLocal threadValues; + private readonly T original; + private readonly IRealmFactory contextFactory; - public Live(T original, IRealmFactory contextFactory) + public Live(T item, IRealmFactory contextFactory) { this.contextFactory = contextFactory; - Guid = original.Guid; - var originalContext = original.Realm; + original = item; + Guid = item.Guid; - threadValues = new ThreadLocal(() => - { - var context = this.contextFactory.Get(); + threadValues = new ThreadLocal(getThreadLocalValue); - if (context == null || originalContext?.IsSameInstance(context) != false) - return original; + // the instance passed in may not be in a managed state. + // for now let's immediately retrieve a managed object on the current thread. + // in the future we may want to delay this until the first access (only populating the Guid at construction time). + if (!item.IsManaged) + original = Get(); + } - return context.Find(Guid); - }); + private T getThreadLocalValue() + { + var context = contextFactory.Get(); + + // only use the original if no context is available or the source realm is the same. + if (context == null || original.Realm?.IsSameInstance(context) == true) return original; + + return context.Find(ID); } ///