diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs index ee0f1684..70eb3baf 100644 --- a/Kyoo.Common/Utility.cs +++ b/Kyoo.Common/Utility.cs @@ -177,6 +177,11 @@ namespace Kyoo return obj; } + public static bool IsOfType([NotNull] object obj, [NotNull] Type type) + { + throw new NotImplementedException(); + } + public static object RunGenericMethod( [NotNull] Type owner, [NotNull] string methodName, diff --git a/Kyoo.CommonAPI/LocalRepository.cs b/Kyoo.CommonAPI/LocalRepository.cs index 4bd1a604..e40bc9a1 100644 --- a/Kyoo.CommonAPI/LocalRepository.cs +++ b/Kyoo.CommonAPI/LocalRepository.cs @@ -12,6 +12,7 @@ using Kyoo.Models.Attributes; using Kyoo.Models.Exceptions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.Metadata; namespace Kyoo.Controllers { @@ -159,12 +160,37 @@ namespace Kyoo.Controllers if (old == null) throw new ItemNotFound($"No resource found with the ID {edited.ID}."); - - foreach (NavigationEntry navigation in Database.Entry(old).Navigations) - if (navigation.Metadata.PropertyInfo.GetCustomAttribute() != null - && navigation.Metadata.GetGetter().GetClrValue(edited) != default) - await navigation.LoadAsync(); + foreach (NavigationEntry navigation in Database.Entry(old).Navigations) + { + if (navigation.Metadata.PropertyInfo.GetCustomAttribute() != null) + { + if (resetOld) + { + await navigation.LoadAsync(); + continue; + } + IClrPropertyGetter getter = navigation.Metadata.GetGetter(); + + if (getter.HasDefaultValue(edited)) + continue; + await navigation.LoadAsync(); + if (getter.GetClrValue(edited) != getter.GetClrValue(old)) + { + navigation.Metadata.PropertyInfo.SetValue(edited, default); + Console.WriteLine($"Loaded: {navigation.Metadata.Name}"); + } + else + Console.WriteLine($"Using: {navigation.Metadata.Name}"); + } + else + { + navigation.Metadata.PropertyInfo.SetValue(edited, default); + Console.WriteLine($"Skipping: {navigation.Metadata.Name}"); + } + } + + Console.WriteLine("Loading done."); if (resetOld) Utility.Nullify(old); Utility.Complete(old, edited); @@ -178,6 +204,11 @@ namespace Kyoo.Controllers } } + protected bool ShouldValidate(T2 value) + { + return value != null && Database.Entry(value).State == EntityState.Detached; + } + protected virtual Task Validate(T resource) { if (string.IsNullOrEmpty(resource.Slug)) @@ -203,7 +234,7 @@ namespace Kyoo.Controllers && !typeof(string).IsAssignableFrom(x.PropertyType))) { object value = property.GetValue(resource); - if (value is ICollection || value == null) + if (value == null || value is ICollection || Utility.IsOfType(value, typeof(ICollection<>))) continue; value = Utility.RunGenericMethod(typeof(Enumerable), "ToList", Utility.GetEnumerableType((IEnumerable)value), value); property.SetValue(resource, value); @@ -299,6 +330,8 @@ namespace Kyoo.Controllers Task IRepository.Create(T item) { + if (item == null) + throw new ArgumentNullException(nameof(item)); TInternal obj = item as TInternal ?? new TInternal(); if (!(item is TInternal)) Utility.Assign(obj, item); @@ -309,6 +342,8 @@ namespace Kyoo.Controllers Task IRepository.CreateIfNotExists(T item, bool silentFail) { + if (item == null) + throw new ArgumentNullException(nameof(item)); TInternal obj = item as TInternal ?? new TInternal(); if (!(item is TInternal)) Utility.Assign(obj, item); @@ -319,6 +354,8 @@ namespace Kyoo.Controllers public Task Edit(T edited, bool resetOld) { + if (edited == null) + throw new ArgumentNullException(nameof(edited)); if (edited is TInternal intern) return Edit(intern, resetOld).Cast(); TInternal obj = new TInternal(); @@ -330,6 +367,8 @@ namespace Kyoo.Controllers Task IRepository.Delete(T obj) { + if (obj == null) + throw new ArgumentNullException(nameof(obj)); if (obj is TInternal intern) return Delete(intern); TInternal item = new TInternal(); diff --git a/Kyoo/Controllers/Repositories/EpisodeRepository.cs b/Kyoo/Controllers/Repositories/EpisodeRepository.cs index 5a9491da..a95bfcad 100644 --- a/Kyoo/Controllers/Repositories/EpisodeRepository.cs +++ b/Kyoo/Controllers/Repositories/EpisodeRepository.cs @@ -120,7 +120,8 @@ namespace Kyoo.Controllers if (resource.ExternalIDs != null) { foreach (MetadataID link in resource.ExternalIDs) - link.Provider = await _providers.CreateIfNotExists(link.Provider, true); + if (ShouldValidate(link)) + link.Provider = await _providers.CreateIfNotExists(link.Provider, true); } } diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs index 99ec0b8e..123285e6 100644 --- a/Kyoo/Controllers/Repositories/LibraryRepository.cs +++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs @@ -76,7 +76,8 @@ namespace Kyoo.Controllers if (resource.ProviderLinks != null) foreach (ProviderLink link in resource.ProviderLinks) - link.Provider = await _providers.CreateIfNotExists(link.Provider, true); + if (ShouldValidate(link)) + link.Provider = await _providers.CreateIfNotExists(link.Provider, true); } public override async Task Delete(LibraryDE obj) diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index 1ec75e24..a0f7c0bb 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -75,7 +75,8 @@ namespace Kyoo.Controllers if (resource.ExternalIDs != null) foreach (MetadataID link in resource.ExternalIDs) - link.Provider = await _providers.CreateIfNotExists(link.Provider, true); + if (ShouldValidate(link)) + link.Provider = await _providers.CreateIfNotExists(link.Provider, true); } public override async Task Delete(People obj) diff --git a/Kyoo/Controllers/Repositories/SeasonRepository.cs b/Kyoo/Controllers/Repositories/SeasonRepository.cs index e75b7790..97bd8319 100644 --- a/Kyoo/Controllers/Repositories/SeasonRepository.cs +++ b/Kyoo/Controllers/Repositories/SeasonRepository.cs @@ -104,7 +104,8 @@ namespace Kyoo.Controllers if (resource.ExternalIDs != null) { foreach (MetadataID link in resource.ExternalIDs) - link.Provider = await _providers.CreateIfNotExists(link.Provider, true); + if (ShouldValidate(link)) + link.Provider = await _providers.CreateIfNotExists(link.Provider, true); } } diff --git a/Kyoo/Controllers/Repositories/ShowRepository.cs b/Kyoo/Controllers/Repositories/ShowRepository.cs index d58c6602..ba0cfed2 100644 --- a/Kyoo/Controllers/Repositories/ShowRepository.cs +++ b/Kyoo/Controllers/Repositories/ShowRepository.cs @@ -111,20 +111,23 @@ namespace Kyoo.Controllers { await base.Validate(resource); - if (resource.Studio != null) + if (ShouldValidate(resource.Studio)) resource.Studio = await _studios.CreateIfNotExists(resource.Studio, true); if (resource.GenreLinks != null) foreach (GenreLink link in resource.GenreLinks) - link.Genre = await _genres.CreateIfNotExists(link.Genre, true); + if (ShouldValidate(link)) + link.Genre = await _genres.CreateIfNotExists(link.Genre, true); if (resource.People != null) foreach (PeopleRole link in resource.People) - link.People = await _people.CreateIfNotExists(link.People, true); + if (ShouldValidate(link)) + link.People = await _people.CreateIfNotExists(link.People, true); if (resource.ExternalIDs != null) foreach (MetadataID link in resource.ExternalIDs) - link.Provider = await _providers.CreateIfNotExists(link.Provider, true); + if (ShouldValidate(link)) + link.Provider = await _providers.CreateIfNotExists(link.Provider, true); } public async Task AddShowLink(int showID, int? libraryID, int? collectionID)