Reworking external ids and adding documentation

This commit is contained in:
Zoe Roux 2021-06-07 00:12:39 +02:00
parent 988135ec12
commit 4ffd526875
19 changed files with 214 additions and 118 deletions

View File

@ -631,10 +631,12 @@ namespace Kyoo.Controllers
/// <param name="where">A predicate to add arbitrary filter</param> /// <param name="where">A predicate to add arbitrary filter</param>
/// <param name="sort">Sort information (sort order & sort by)</param> /// <param name="sort">Sort information (sort order & sort by)</param>
/// <param name="limit">Pagination information (where to start and how many to get)</param> /// <param name="limit">Pagination information (where to start and how many to get)</param>
/// <typeparam name="T">The type of metadata to retrieve</typeparam>
/// <returns>A filtered list of external ids.</returns> /// <returns>A filtered list of external ids.</returns>
Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null, Task<ICollection<MetadataID<T>>> GetMetadataID<T>(Expression<Func<MetadataID<T>, bool>> where = null,
Sort<MetadataID> sort = default, Sort<MetadataID<T>> sort = default,
Pagination limit = default); Pagination limit = default)
where T : class, IResource;
/// <summary> /// <summary>
/// Get a list of external ids that match all filters /// Get a list of external ids that match all filters
@ -643,10 +645,11 @@ namespace Kyoo.Controllers
/// <param name="sort">A sort by expression</param> /// <param name="sort">A sort by expression</param>
/// <param name="limit">Pagination information (where to start and how many to get)</param> /// <param name="limit">Pagination information (where to start and how many to get)</param>
/// <returns>A filtered list of external ids.</returns> /// <returns>A filtered list of external ids.</returns>
Task<ICollection<MetadataID>> GetMetadataID([Optional] Expression<Func<MetadataID, bool>> where, Task<ICollection<MetadataID<T>>> GetMetadataID<T>([Optional] Expression<Func<MetadataID<T>, bool>> where,
Expression<Func<MetadataID, object>> sort, Expression<Func<MetadataID<T>, object>> sort,
Pagination limit = default Pagination limit = default
) => GetMetadataID(where, new Sort<MetadataID>(sort), limit); ) where T : class, IResource
=> GetMetadataID(where, new Sort<MetadataID<T>>(sort), limit);
} }
/// <summary> /// <summary>

View File

@ -250,9 +250,9 @@ namespace Kyoo.Controllers
(Show s, nameof(Show.ExternalIDs)) => SetRelation(s, (Show s, nameof(Show.ExternalIDs)) => SetRelation(s,
ProviderRepository.GetMetadataID(x => x.ShowID == obj.ID), ProviderRepository.GetMetadataID<Show>(x => x.FirstID == obj.ID),
(x, y) => x.ExternalIDs = y, (x, y) => x.ExternalIDs = y,
(x, y) => { x.Show = y; x.ShowID = y.ID; }), (x, y) => { x.First = y; x.FirstID = y.ID; }),
(Show s, nameof(Show.Genres)) => GenreRepository (Show s, nameof(Show.Genres)) => GenreRepository
.GetAll(x => x.Shows.Any(y => y.ID == obj.ID)) .GetAll(x => x.Shows.Any(y => y.ID == obj.ID))
@ -290,9 +290,9 @@ namespace Kyoo.Controllers
(Season s, nameof(Season.ExternalIDs)) => SetRelation(s, (Season s, nameof(Season.ExternalIDs)) => SetRelation(s,
ProviderRepository.GetMetadataID(x => x.SeasonID == obj.ID), ProviderRepository.GetMetadataID<Season>(x => x.FirstID == obj.ID),
(x, y) => x.ExternalIDs = y, (x, y) => x.ExternalIDs = y,
(x, y) => { x.Season = y; x.SeasonID = y.ID; }), (x, y) => { x.First = y; x.FirstID = y.ID; }),
(Season s, nameof(Season.Episodes)) => SetRelation(s, (Season s, nameof(Season.Episodes)) => SetRelation(s,
EpisodeRepository.GetAll(x => x.Season.ID == obj.ID), EpisodeRepository.GetAll(x => x.Season.ID == obj.ID),
@ -309,9 +309,9 @@ namespace Kyoo.Controllers
(Episode e, nameof(Episode.ExternalIDs)) => SetRelation(e, (Episode e, nameof(Episode.ExternalIDs)) => SetRelation(e,
ProviderRepository.GetMetadataID(x => x.EpisodeID == obj.ID), ProviderRepository.GetMetadataID<Episode>(x => x.FirstID == obj.ID),
(x, y) => x.ExternalIDs = y, (x, y) => x.ExternalIDs = y,
(x, y) => { x.Episode = y; x.EpisodeID = y.ID; }), (x, y) => { x.First = y; x.FirstID = y.ID; }),
(Episode e, nameof(Episode.Tracks)) => SetRelation(e, (Episode e, nameof(Episode.Tracks)) => SetRelation(e,
TrackRepository.GetAll(x => x.Episode.ID == obj.ID), TrackRepository.GetAll(x => x.Episode.ID == obj.ID),
@ -355,9 +355,9 @@ namespace Kyoo.Controllers
(People p, nameof(People.ExternalIDs)) => SetRelation(p, (People p, nameof(People.ExternalIDs)) => SetRelation(p,
ProviderRepository.GetMetadataID(x => x.PeopleID == obj.ID), ProviderRepository.GetMetadataID<People>(x => x.FirstID == obj.ID),
(x, y) => x.ExternalIDs = y, (x, y) => x.ExternalIDs = y,
(x, y) => { x.People = y; x.PeopleID = y.ID; }), (x, y) => { x.First = y; x.FirstID = y.ID; }),
(People p, nameof(People.Roles)) => PeopleRepository (People p, nameof(People.Roles)) => PeopleRepository
.GetFromPeople(obj.ID) .GetFromPeople(obj.ID)

View File

@ -1,33 +1,20 @@
using Kyoo.Models.Attributes;
namespace Kyoo.Models namespace Kyoo.Models
{ {
/// <summary> /// <summary>
/// ID and link of an item on an external provider. /// ID and link of an item on an external provider.
/// </summary> /// </summary>
public class MetadataID /// <typeparam name="T"></typeparam>
public class MetadataID<T> : Link<T, Provider>
where T : class, IResource
{ {
/// <summary> /// <summary>
/// The unique ID of this metadata. This is the equivalent of <see cref="IResource.ID"/>. /// The ID of the resource on the external provider.
/// </summary> /// </summary>
[SerializeIgnore] public int ID { get; set; }
[SerializeIgnore] public int ProviderID { get; set; }
public Provider Provider {get; set; }
[SerializeIgnore] public int? ShowID { get; set; }
[SerializeIgnore] public Show Show { get; set; }
[SerializeIgnore] public int? EpisodeID { get; set; }
[SerializeIgnore] public Episode Episode { get; set; }
[SerializeIgnore] public int? SeasonID { get; set; }
[SerializeIgnore] public Season Season { get; set; }
[SerializeIgnore] public int? PeopleID { get; set; }
[SerializeIgnore] public People People { get; set; }
public string DataID { get; set; } public string DataID { get; set; }
/// <summary>
/// The URL of the resource on the external provider.
/// </summary>
public string Link { get; set; } public string Link { get; set; }
} }
} }

View File

@ -3,22 +3,45 @@ using System.Linq;
namespace Kyoo.Models namespace Kyoo.Models
{ {
/// <summary>
/// A page of resource that contains information about the pagination of resources.
/// </summary>
/// <typeparam name="T">The type of resource contained in this page.</typeparam>
public class Page<T> where T : IResource public class Page<T> where T : IResource
{ {
public string This { get; set; } /// <summary>
public string First { get; set; } /// The link of the current page.
public string Next { get; set; } /// </summary>
public string This { get; }
/// <summary>
/// The link of the first page.
/// </summary>
public string First { get; }
/// <summary>
/// The link of the next page.
/// </summary>
public string Next { get; }
/// <summary>
/// The number of items in the current page.
/// </summary>
public int Count => Items.Count; public int Count => Items.Count;
public ICollection<T> Items { get; set; }
/// <summary>
public Page() { } /// The list of items in the page.
/// </summary>
public Page(ICollection<T> items) public ICollection<T> Items { get; }
{
Items = items;
} /// <summary>
/// Create a new <see cref="Page{T}"/>.
/// </summary>
/// <param name="items">The list of items in the page.</param>
/// <param name="this">The link of the current page.</param>
/// <param name="next">The link of the next page.</param>
/// <param name="first">The link of the first page.</param>
public Page(ICollection<T> items, string @this, string next, string first) public Page(ICollection<T> items, string @this, string next, string first)
{ {
Items = items; Items = items;
@ -27,7 +50,14 @@ namespace Kyoo.Models
First = first; First = first;
} }
public Page(ICollection<T> items, /// <summary>
/// Create a new <see cref="Page{T}"/> and compute the urls.
/// </summary>
/// <param name="items">The list of items in the page.</param>
/// <param name="url">The base url of the resources available from this page.</param>
/// <param name="query">The list of query strings of the current page</param>
/// <param name="limit">The number of items requested for the current page.</param>
public Page(ICollection<T> items,
string url, string url,
Dictionary<string, string> query, Dictionary<string, string> query,
int limit) int limit)

View File

@ -1,17 +1,55 @@
using Kyoo.Models.Attributes;
namespace Kyoo.Models namespace Kyoo.Models
{ {
/// <summary>
/// A role a person played for a show. It can be an actor, musician, voice actor, director, writer...
/// </summary>
/// <remarks>
/// This class is not serialized like other classes.
/// Based on the <see cref="ForPeople"/> field, it is serialized like
/// a show with two extra fields (<see cref="Role"/> and <see cref="Type"/>).
/// </remarks>
public class PeopleRole : IResource public class PeopleRole : IResource
{ {
[SerializeIgnore] public int ID { get; set; } /// <inheritdoc />
[SerializeIgnore] public string Slug => ForPeople ? Show.Slug : People.Slug; public int ID { get; set; }
[SerializeIgnore] public bool ForPeople;
[SerializeIgnore] public int PeopleID { get; set; } /// <inheritdoc />
[SerializeIgnore] public virtual People People { get; set; } public string Slug => ForPeople ? Show.Slug : People.Slug;
[SerializeIgnore] public int ShowID { get; set; }
[SerializeIgnore] public virtual Show Show { get; set; } /// <summary>
public string Role { get; set; } /// Should this role be used as a Show substitute (the value is <c>false</c>) or
/// as a People substitute (the value is <c>true</c>).
/// </summary>
public bool ForPeople { get; set; }
/// <summary>
/// The ID of the People playing the role.
/// </summary>
public int PeopleID { get; set; }
/// <summary>
/// The people that played this role.
/// </summary>
public People People { get; set; }
/// <summary>
/// The ID of the Show where the People playing in.
/// </summary>
public int ShowID { get; set; }
/// <summary>
/// The show where the People played in.
/// </summary>
public Show Show { get; set; }
/// <summary>
/// The type of work the person has done for the show.
/// That can be something like "Actor", "Writer", "Music", "Voice Actor"...
/// </summary>
public string Type { get; set; } public string Type { get; set; }
/// <summary>
/// The role the People played.
/// This is mostly used to inform witch character was played for actor and voice actors.
/// </summary>
public string Role { get; set; }
} }
} }

View File

@ -86,9 +86,9 @@ namespace Kyoo.Models
public DateTime? ReleaseDate { get; set; } public DateTime? ReleaseDate { get; set; }
/// <summary> /// <summary>
/// The link to metadata providers that this episode has. See <see cref="MetadataID"/> for more information. /// The link to metadata providers that this episode has. See <see cref="MetadataID{T}"/> for more information.
/// </summary> /// </summary>
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID<Episode>> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of tracks this episode has. This lists video, audio and subtitles available. /// The list of tracks this episode has. This lists video, audio and subtitles available.

View File

@ -27,9 +27,9 @@ namespace Kyoo.Models
[SerializeAs("{HOST}/api/people/{Slug}/poster")] public string Poster { get; set; } [SerializeAs("{HOST}/api/people/{Slug}/poster")] public string Poster { get; set; }
/// <summary> /// <summary>
/// The link to metadata providers that this person has. See <see cref="MetadataID"/> for more information. /// The link to metadata providers that this person has. See <see cref="MetadataID{T}"/> for more information.
/// </summary> /// </summary>
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID<People>> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information. /// The list of roles this person has played in. See <see cref="PeopleRole"/> for more information.

View File

@ -44,11 +44,6 @@ namespace Kyoo.Models
/// The internal link between this provider and libraries in the <see cref="Libraries"/> list. /// The internal link between this provider and libraries in the <see cref="Libraries"/> list.
/// </summary> /// </summary>
[Link] public ICollection<Link<Library, Provider>> LibraryLinks { get; set; } [Link] public ICollection<Link<Library, Provider>> LibraryLinks { get; set; }
/// <summary>
/// The internal link between this provider and related <see cref="MetadataID"/>.
/// </summary>
[Link] public ICollection<MetadataID> MetadataLinks { get; set; }
#endif #endif
/// <summary> /// <summary>

View File

@ -63,9 +63,9 @@ namespace Kyoo.Models
[SerializeAs("{HOST}/api/seasons/{Slug}/thumb")] public string Poster { get; set; } [SerializeAs("{HOST}/api/seasons/{Slug}/thumb")] public string Poster { get; set; }
/// <summary> /// <summary>
/// The link to metadata providers that this episode has. See <see cref="MetadataID"/> for more information. /// The link to metadata providers that this episode has. See <see cref="MetadataID{T}"/> for more information.
/// </summary> /// </summary>
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID<Season>> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The list of episodes that this season contains. /// The list of episodes that this season contains.

View File

@ -89,9 +89,9 @@ namespace Kyoo.Models
public bool IsMovie { get; set; } public bool IsMovie { get; set; }
/// <summary> /// <summary>
/// The link to metadata providers that this show has. See <see cref="MetadataID"/> for more information. /// The link to metadata providers that this show has. See <see cref="MetadataID{T}"/> for more information.
/// </summary> /// </summary>
[EditableRelation] [LoadableRelation] public ICollection<MetadataID> ExternalIDs { get; set; } [EditableRelation] [LoadableRelation] public ICollection<MetadataID<Show>> ExternalIDs { get; set; }
/// <summary> /// <summary>
/// The ID of the Studio that made this show. This value is only set when the <see cref="Studio"/> has been loaded. /// The ID of the Studio that made this show. This value is only set when the <see cref="Studio"/> has been loaded.
@ -155,18 +155,18 @@ namespace Kyoo.Models
/// </summary> /// </summary>
/// <remarks>This method will never return anything if the <see cref="ExternalIDs"/> are not loaded.</remarks> /// <remarks>This method will never return anything if the <see cref="ExternalIDs"/> are not loaded.</remarks>
/// <param name="provider">The slug of the provider</param> /// <param name="provider">The slug of the provider</param>
/// <returns>The <see cref="MetadataID.DataID"/> field of the asked provider.</returns> /// <returns>The <see cref="MetadataID{T}.DataID"/> field of the asked provider.</returns>
public string GetID(string provider) public string GetID(string provider)
{ {
return ExternalIDs?.FirstOrDefault(x => x.Provider.Slug == provider)?.DataID; return ExternalIDs?.FirstOrDefault(x => x.Second.Slug == provider)?.DataID;
} }
/// <inheritdoc /> /// <inheritdoc />
public void OnMerge(object merged) public void OnMerge(object merged)
{ {
if (ExternalIDs != null) if (ExternalIDs != null)
foreach (MetadataID id in ExternalIDs) foreach (MetadataID<Show> id in ExternalIDs)
id.Show = this; id.First = this;
if (People != null) if (People != null)
foreach (PeopleRole link in People) foreach (PeopleRole link in People)
link.Show = this; link.Show = this;

View File

@ -2,14 +2,44 @@
namespace Kyoo.Models namespace Kyoo.Models
{ {
/// <summary>
/// Results of a search request.
/// </summary>
public class SearchResult public class SearchResult
{ {
public string Query; /// <summary>
public IEnumerable<Collection> Collections; /// The query of the search request.
public IEnumerable<Show> Shows; /// </summary>
public IEnumerable<Episode> Episodes; public string Query { get; init; }
public IEnumerable<People> People;
public IEnumerable<Genre> Genres; /// <summary>
public IEnumerable<Studio> Studios; /// The collections that matched the search.
/// </summary>
public ICollection<Collection> Collections { get; init; }
/// <summary>
/// The shows that matched the search.
/// </summary>
public ICollection<Show> Shows { get; init; }
/// <summary>
/// The episodes that matched the search.
/// </summary>
public ICollection<Episode> Episodes { get; init; }
/// <summary>
/// The people that matched the search.
/// </summary>
public ICollection<People> People { get; init; }
/// <summary>
/// The genres that matched the search.
/// </summary>
public ICollection<Genre> Genres { get; init; }
/// <summary>
/// The studios that matched the search.
/// </summary>
public ICollection<Studio> Studios { get; init; }
} }
} }

View File

@ -7,7 +7,6 @@ using System.Reflection;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
namespace Kyoo namespace Kyoo

View File

@ -61,10 +61,6 @@ namespace Kyoo
/// </summary> /// </summary>
public DbSet<Provider> Providers { get; set; } public DbSet<Provider> Providers { get; set; }
/// <summary> /// <summary>
/// All metadataIDs (ExternalIDs) of Kyoo. See <see cref="MetadataID"/>.
/// </summary>
public DbSet<MetadataID> MetadataIds { get; set; }
/// <summary>
/// The list of registered users. /// The list of registered users.
/// </summary> /// </summary>
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
@ -79,6 +75,17 @@ namespace Kyoo
/// </summary> /// </summary>
public DbSet<WatchedEpisode> WatchedEpisodes { get; set; } public DbSet<WatchedEpisode> WatchedEpisodes { get; set; }
/// <summary>
/// Get all metadataIDs (ExternalIDs) of a given resource. See <see cref="MetadataID{T}"/>.
/// </summary>
/// <typeparam name="T">The metadata of this type will be returned.</typeparam>
/// <returns>A queryable of metadata ids for a type.</returns>
public DbSet<MetadataID<T>> MetadataIds<T>()
where T : class, IResource
{
return Set<MetadataID<T>>();
}
/// <summary> /// <summary>
/// Get a generic link between two resource types. /// Get a generic link between two resource types.
/// </summary> /// </summary>
@ -205,25 +212,33 @@ namespace Kyoo
.WithMany(x => x.ShowLinks), .WithMany(x => x.ShowLinks),
y => y.HasKey(Link<User, Show>.PrimaryKey)); y => y.HasKey(Link<User, Show>.PrimaryKey));
modelBuilder.Entity<MetadataID>() modelBuilder.Entity<MetadataID<Show>>()
.HasOne(x => x.Show) .HasOne(x => x.First)
.WithMany(x => x.ExternalIDs) .WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>() modelBuilder.Entity<MetadataID<Season>>()
.HasOne(x => x.Season) .HasOne(x => x.First)
.WithMany(x => x.ExternalIDs) .WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>() modelBuilder.Entity<MetadataID<Episode>>()
.HasOne(x => x.Episode) .HasOne(x => x.First)
.WithMany(x => x.ExternalIDs) .WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>() modelBuilder.Entity<MetadataID<People>>()
.HasOne(x => x.People) .HasOne(x => x.First)
.WithMany(x => x.ExternalIDs) .WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>()
.HasOne(x => x.Provider)
.WithMany(x => x.MetadataLinks) modelBuilder.Entity<MetadataID<Show>>().HasOne(x => x.Second).WithMany()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID<Season>>().HasOne(x => x.Second).WithMany()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID<Episode>>().HasOne(x => x.Second).WithMany()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID<People>>().HasOne(x => x.Second).WithMany()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID<Show>>().HasOne(x => x.Second).WithMany()
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<WatchedEpisode>() modelBuilder.Entity<WatchedEpisode>()

View File

@ -234,9 +234,9 @@ namespace Kyoo.Controllers
await base.Validate(resource); await base.Validate(resource);
resource.ExternalIDs = await resource.ExternalIDs.SelectAsync(async x => resource.ExternalIDs = await resource.ExternalIDs.SelectAsync(async x =>
{ {
x.Provider = await _providers.CreateIfNotExists(x.Provider); x.Second = await _providers.CreateIfNotExists(x.Second);
x.ProviderID = x.Provider.ID; x.SecondID = x.Second.ID;
_database.Entry(x.Provider).State = EntityState.Detached; _database.Entry(x.Second).State = EntityState.Detached;
return x; return x;
}).ToListAsync(); }).ToListAsync();
} }

View File

@ -73,9 +73,9 @@ namespace Kyoo.Controllers
await base.Validate(resource); await base.Validate(resource);
await resource.ExternalIDs.ForEachAsync(async id => await resource.ExternalIDs.ForEachAsync(async id =>
{ {
id.Provider = await _providers.CreateIfNotExists(id.Provider); id.Second = await _providers.CreateIfNotExists(id.Second);
id.ProviderID = id.Provider.ID; id.SecondID = id.Second.ID;
_database.Entry(id.Provider).State = EntityState.Detached; _database.Entry(id.Second).State = EntityState.Detached;
}); });
await resource.Roles.ForEachAsync(async role => await resource.Roles.ForEachAsync(async role =>
{ {

View File

@ -58,18 +58,18 @@ namespace Kyoo.Controllers
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
obj.MetadataLinks.ForEach(x => _database.Entry(x).State = EntityState.Deleted);
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
/// <inheritdoc /> /// <inheritdoc />
public Task<ICollection<MetadataID>> GetMetadataID(Expression<Func<MetadataID, bool>> where = null, public Task<ICollection<MetadataID<T>>> GetMetadataID<T>(Expression<Func<MetadataID<T>, bool>> where = null,
Sort<MetadataID> sort = default, Sort<MetadataID<T>> sort = default,
Pagination limit = default) Pagination limit = default)
where T : class, IResource
{ {
return ApplyFilters(_database.MetadataIds.Include(y => y.Provider), return ApplyFilters(_database.MetadataIds<T>().Include(y => y.Second),
x => _database.MetadataIds.FirstOrDefaultAsync(y => y.ID == x), x => _database.MetadataIds<T>().FirstOrDefaultAsync(y => y.FirstID == x),
x => x.ID, x => x.FirstID,
where, where,
sort, sort,
limit); limit);

View File

@ -160,9 +160,9 @@ namespace Kyoo.Controllers
await base.Validate(resource); await base.Validate(resource);
await resource.ExternalIDs.ForEachAsync(async id => await resource.ExternalIDs.ForEachAsync(async id =>
{ {
id.Provider = await _providers.CreateIfNotExists(id.Provider); id.Second = await _providers.CreateIfNotExists(id.Second);
id.ProviderID = id.Provider.ID; id.SecondID = id.Second.ID;
_database.Entry(id.Provider).State = EntityState.Detached; _database.Entry(id.Second).State = EntityState.Detached;
}); });
} }

View File

@ -111,9 +111,9 @@ namespace Kyoo.Controllers
.ToList(); .ToList();
await resource.ExternalIDs.ForEachAsync(async id => await resource.ExternalIDs.ForEachAsync(async id =>
{ {
id.Provider = await _providers.CreateIfNotExists(id.Provider); id.Second = await _providers.CreateIfNotExists(id.Second);
id.ProviderID = id.Provider.ID; id.SecondID = id.Second.ID;
_database.Entry(id.Provider).State = EntityState.Detached; _database.Entry(id.Second).State = EntityState.Detached;
}); });
await resource.People.ForEachAsync(async role => await resource.People.ForEachAsync(async role =>
{ {
@ -196,7 +196,7 @@ namespace Kyoo.Controllers
_database.Entry(entry).State = EntityState.Deleted; _database.Entry(entry).State = EntityState.Deleted;
if (obj.ExternalIDs != null) if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs) foreach (MetadataID<Show> entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Deleted; _database.Entry(entry).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();

View File

@ -4,7 +4,6 @@ using Kyoo.Authentication;
using Kyoo.Controllers; using Kyoo.Controllers;
using Kyoo.Models; using Kyoo.Models;
using Kyoo.Models.Options; using Kyoo.Models.Options;
using Kyoo.Postgresql;
using Kyoo.SqLite; using Kyoo.SqLite;
using Kyoo.Tasks; using Kyoo.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;