Removing most of the things needed for a custom many to many

This commit is contained in:
Zoe Roux 2021-03-01 00:49:03 +01:00
parent b2b53f2691
commit fef6a93a1d
22 changed files with 70 additions and 432 deletions

View File

@ -239,6 +239,23 @@ namespace Kyoo
return types.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType); return types.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
} }
public static async IAsyncEnumerable<T2> SelectAsync<T, T2>(this IEnumerable<T> self, Func<T, Task<T2>> mapper)
{
using IEnumerator<T> enumerator = self.GetEnumerator();
while (enumerator.MoveNext())
yield return await mapper(enumerator.Current);
}
public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> self)
{
List<T> ret = new();
await foreach(T i in self)
ret.Add(i);
return ret;
}
public static IEnumerable<T> IfEmpty<T>(this IEnumerable<T> self, Action action) public static IEnumerable<T> IfEmpty<T>(this IEnumerable<T> self, Action action)
{ {
using IEnumerator<T> enumerator = self.GetEnumerator(); using IEnumerator<T> enumerator = self.GetEnumerator();

View File

@ -15,7 +15,7 @@ using Microsoft.EntityFrameworkCore.Metadata;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public abstract class LocalRepository<T> public abstract class LocalRepository<T> : IRepository<T>
where T : class, IResource where T : class, IResource
{ {
protected readonly DbContext Database; protected readonly DbContext Database;
@ -53,6 +53,8 @@ namespace Kyoo.Controllers
return Database.Set<T>().FirstOrDefaultAsync(predicate); return Database.Set<T>().FirstOrDefaultAsync(predicate);
} }
public abstract Task<ICollection<T>> Search(string query);
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null, public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
Sort<T> sort = default, Sort<T> sort = default,
Pagination limit = default) Pagination limit = default)
@ -256,112 +258,4 @@ namespace Kyoo.Controllers
await Delete(slug); await Delete(slug);
} }
} }
public abstract class LocalRepository<T, TInternal> : LocalRepository<TInternal>, IRepository<T>
where T : class, IResource
where TInternal : class, T, new()
{
protected LocalRepository(DbContext database) : base(database) { }
public new Task<T> Get(int id)
{
return base.Get(id).Cast<T>();
}
public new Task<T> Get(string slug)
{
return base.Get(slug).Cast<T>();
}
public Task<T> Get(Expression<Func<T, bool>> predicate)
{
return Get(predicate.Convert<Func<TInternal, bool>>()).Cast<T>();
}
public abstract Task<ICollection<T>> Search(string query);
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
Sort<T> sort = default,
Pagination limit = default)
{
return ApplyFilters(Database.Set<TInternal>(), where, sort, limit);
}
protected virtual async Task<ICollection<T>> ApplyFilters(IQueryable<TInternal> query,
Expression<Func<T, bool>> where = null,
Sort<T> sort = default,
Pagination limit = default)
{
ICollection<TInternal> items = await ApplyFilters(query,
base.Get,
DefaultSort,
where.Convert<Func<TInternal, bool>>(),
sort.To<TInternal>(),
limit);
return items.ToList<T>();
}
public virtual Task<int> GetCount(Expression<Func<T, bool>> where = null)
{
IQueryable<TInternal> query = Database.Set<TInternal>();
if (where != null)
query = query.Where(where.Convert<Func<TInternal, bool>>());
return query.CountAsync();
}
Task<T> IRepository<T>.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);
return Create(obj).Cast<T>()
.Then(x => item.ID = x.ID);
}
Task<T> IRepository<T>.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);
return CreateIfNotExists(obj, silentFail).Cast<T>()
.Then(x => item.ID = x.ID);
}
public Task<T> Edit(T edited, bool resetOld)
{
if (edited == null)
throw new ArgumentNullException(nameof(edited));
if (edited is TInternal intern)
return Edit(intern, resetOld).Cast<T>();
TInternal obj = new();
Utility.Assign(obj, edited);
return base.Edit(obj, resetOld).Cast<T>();
}
public abstract override Task Delete([NotNull] TInternal obj);
Task IRepository<T>.Delete(T obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (obj is TInternal intern)
return Delete(intern);
TInternal item = new();
Utility.Assign(item, obj);
return Delete(item);
}
public virtual async Task DeleteRange(IEnumerable<T> objs)
{
foreach (T obj in objs)
await ((IRepository<T>)this).Delete(obj);
}
}
} }

View File

@ -8,11 +8,11 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public class CollectionRepository : LocalRepository<Collection, CollectionDE>, ICollectionRepository public class CollectionRepository : LocalRepository<Collection>, ICollectionRepository
{ {
private bool _disposed; private bool _disposed;
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
protected override Expression<Func<CollectionDE, object>> DefaultSort => x => x.Name; protected override Expression<Func<Collection, object>> DefaultSort => x => x.Name;
public CollectionRepository(DatabaseContext database) : base(database) public CollectionRepository(DatabaseContext database) : base(database)
{ {
@ -40,10 +40,10 @@ namespace Kyoo.Controllers
return await _database.Collections return await _database.Collections
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
.Take(20) .Take(20)
.ToListAsync<Collection>(); .ToListAsync();
} }
public override async Task<CollectionDE> Create(CollectionDE obj) public override async Task<Collection> Create(Collection obj)
{ {
await base.Create(obj); await base.Create(obj);
_database.Entry(obj).State = EntityState.Added; _database.Entry(obj).State = EntityState.Added;
@ -51,18 +51,12 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
public override async Task Delete(CollectionDE obj) public override async Task Delete(Collection obj)
{ {
if (obj == null) if (obj == null)
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
if (obj.Links != null)
foreach (CollectionLink link in obj.Links)
_database.Entry(link).State = EntityState.Deleted;
if (obj.LibraryLinks != null)
foreach (LibraryLink link in obj.LibraryLinks)
_database.Entry(link).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
} }

View File

@ -86,7 +86,7 @@ namespace Kyoo.Controllers
&& x.AbsoluteNumber == absoluteNumber); && x.AbsoluteNumber == absoluteNumber);
} }
public async Task<ICollection<Episode>> Search(string query) public override async Task<ICollection<Episode>> Search(string query)
{ {
return await _database.Episodes return await _database.Episodes
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Title, $"%{query}%"))

View File

@ -8,11 +8,11 @@ using Microsoft.EntityFrameworkCore;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public class GenreRepository : LocalRepository<Genre, GenreDE>, IGenreRepository public class GenreRepository : LocalRepository<Genre>, IGenreRepository
{ {
private bool _disposed; private bool _disposed;
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
protected override Expression<Func<GenreDE, object>> DefaultSort => x => x.Slug; protected override Expression<Func<Genre, object>> DefaultSort => x => x.Slug;
public GenreRepository(DatabaseContext database) : base(database) public GenreRepository(DatabaseContext database) : base(database)
@ -41,10 +41,10 @@ namespace Kyoo.Controllers
return await _database.Genres return await _database.Genres
.Where(genre => EF.Functions.ILike(genre.Name, $"%{query}%")) .Where(genre => EF.Functions.ILike(genre.Name, $"%{query}%"))
.Take(20) .Take(20)
.ToListAsync<Genre>(); .ToListAsync();
} }
public override async Task<GenreDE> Create(GenreDE obj) public override async Task<Genre> Create(Genre obj)
{ {
await base.Create(obj); await base.Create(obj);
_database.Entry(obj).State = EntityState.Added; _database.Entry(obj).State = EntityState.Added;
@ -52,15 +52,12 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
public override async Task Delete(GenreDE obj) public override async Task Delete(Genre obj)
{ {
if (obj == null) if (obj == null)
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
if (obj.Links != null)
foreach (GenreLink link in obj.Links)
_database.Entry(link).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
} }

View File

@ -71,7 +71,7 @@ namespace Kyoo.Controllers
private IQueryable<LibraryItem> ItemsQuery private IQueryable<LibraryItem> ItemsQuery
=> _database.Shows => _database.Shows
// .Where(x => !_database.CollectionLinks.Any(y => y.ChildID == x.ID)) .Where(x => !_database.CollectionLinks.Any(y => y.ChildID == x.ID))
.Select(LibraryItem.FromShow) .Select(LibraryItem.FromShow)
.Concat(_database.Collections .Concat(_database.Collections
.Select(LibraryItem.FromCollection)); .Select(LibraryItem.FromCollection));
@ -114,18 +114,17 @@ namespace Kyoo.Controllers
public override Task Delete(LibraryItem obj) => throw new InvalidOperationException(); public override Task Delete(LibraryItem obj) => throw new InvalidOperationException();
private IQueryable<LibraryItem> LibraryRelatedQuery(Expression<Func<LibraryLink, bool>> selector) private IQueryable<LibraryItem> LibraryRelatedQuery(Expression<Func<LibraryLink, bool>> selector)
=> throw new NotImplementedException(); => _database.LibraryLinks
// => _database.LibraryLinks .Where(selector)
// .Where(selector) .Select(x => x.Show)
// .Select(x => x.Show) .Where(x => x != null)
// .Where(x => x != null) .Where(x => !_database.CollectionLinks.Any(y => y.ChildID == x.ID))
// .Where(x => !_database.CollectionLinks.Any(y => y.ChildID == x.ID)) .Select(LibraryItem.FromShow)
// .Select(LibraryItem.FromShow) .Concat(_database.LibraryLinks
// .Concat(_database.LibraryLinks .Where(selector)
// .Where(selector) .Select(x => x.Collection)
// .Select(x => x.Collection) .Where(x => x != null)
// .Where(x => x != null) .Select(LibraryItem.FromCollection));
// .Select(LibraryItem.FromCollection));
public async Task<ICollection<LibraryItem>> GetFromLibrary(int id, public async Task<ICollection<LibraryItem>> GetFromLibrary(int id,
Expression<Func<LibraryItem, bool>> where = null, Expression<Func<LibraryItem, bool>> where = null,

View File

@ -10,12 +10,12 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public class LibraryRepository : LocalRepository<Library, LibraryDE>, ILibraryRepository public class LibraryRepository : LocalRepository<Library>, ILibraryRepository
{ {
private bool _disposed; private bool _disposed;
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
protected override Expression<Func<LibraryDE, object>> DefaultSort => x => x.ID; protected override Expression<Func<Library, object>> DefaultSort => x => x.ID;
public LibraryRepository(DatabaseContext database, IProviderRepository providers) public LibraryRepository(DatabaseContext database, IProviderRepository providers)
@ -48,22 +48,18 @@ namespace Kyoo.Controllers
return await _database.Libraries return await _database.Libraries
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
.Take(20) .Take(20)
.ToListAsync<Library>(); .ToListAsync();
} }
public override async Task<LibraryDE> Create(LibraryDE obj) public override async Task<Library> Create(Library obj)
{ {
await base.Create(obj); await base.Create(obj);
_database.Entry(obj).State = EntityState.Added; _database.Entry(obj).State = EntityState.Added;
if (obj.ProviderLinks != null)
foreach (ProviderLink entry in obj.ProviderLinks)
_database.Entry(entry).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated library (slug {obj.Slug} already exists)."); await _database.SaveChangesAsync($"Trying to insert a duplicated library (slug {obj.Slug} already exists).");
return obj; return obj;
} }
protected override async Task Validate(LibraryDE resource) protected override async Task Validate(Library resource)
{ {
if (string.IsNullOrEmpty(resource.Slug)) if (string.IsNullOrEmpty(resource.Slug))
throw new ArgumentException("The library's slug must be set and not empty"); throw new ArgumentException("The library's slug must be set and not empty");
@ -74,24 +70,17 @@ namespace Kyoo.Controllers
await base.Validate(resource); await base.Validate(resource);
if (resource.ProviderLinks != null) resource.Providers = await resource.Providers
foreach (ProviderLink link in resource.ProviderLinks) .SelectAsync(x => _providers.CreateIfNotExists(x, true))
if (ShouldValidate(link)) .ToListAsync();
link.Child = await _providers.CreateIfNotExists(link.Child, true);
} }
public override async Task Delete(LibraryDE obj) public override async Task Delete(Library obj)
{ {
if (obj == null) if (obj == null)
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
if (obj.ProviderLinks != null)
foreach (ProviderLink entry in obj.ProviderLinks)
_database.Entry(entry).State = EntityState.Deleted;
if (obj.Links != null)
foreach (LibraryLink entry in obj.Links)
_database.Entry(entry).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
} }
} }

View File

@ -49,7 +49,7 @@ namespace Kyoo.Controllers
await _shows.Value.DisposeAsync(); await _shows.Value.DisposeAsync();
} }
public async Task<ICollection<People>> Search(string query) public override async Task<ICollection<People>> Search(string query)
{ {
return await _database.People return await _database.People
.Where(people => EF.Functions.ILike(people.Name, $"%{query}%")) .Where(people => EF.Functions.ILike(people.Name, $"%{query}%"))

View File

@ -19,7 +19,7 @@ namespace Kyoo.Controllers
_database = database; _database = database;
} }
public async Task<ICollection<ProviderID>> Search(string query) public override async Task<ICollection<ProviderID>> Search(string query)
{ {
return await _database.Providers return await _database.Providers
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))

View File

@ -74,7 +74,7 @@ namespace Kyoo.Controllers
&& x.SeasonNumber == seasonNumber); && x.SeasonNumber == seasonNumber);
} }
public async Task<ICollection<Season>> Search(string query) public override async Task<ICollection<Season>> Search(string query)
{ {
return await _database.Seasons return await _database.Seasons
.Where(x => EF.Functions.ILike(x.Title, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Title, $"%{query}%"))

View File

@ -9,7 +9,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace Kyoo.Controllers namespace Kyoo.Controllers
{ {
public class ShowRepository : LocalRepository<Show, ShowDE>, IShowRepository public class ShowRepository : LocalRepository<Show>, IShowRepository
{ {
private bool _disposed; private bool _disposed;
private readonly DatabaseContext _database; private readonly DatabaseContext _database;
@ -19,7 +19,7 @@ namespace Kyoo.Controllers
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
private readonly Lazy<ISeasonRepository> _seasons; private readonly Lazy<ISeasonRepository> _seasons;
private readonly Lazy<IEpisodeRepository> _episodes; private readonly Lazy<IEpisodeRepository> _episodes;
protected override Expression<Func<ShowDE, object>> DefaultSort => x => x.Title; protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
public ShowRepository(DatabaseContext database, public ShowRepository(DatabaseContext database,
IStudioRepository studios, IStudioRepository studios,
@ -81,21 +81,11 @@ namespace Kyoo.Controllers
.ToListAsync<Show>(); .ToListAsync<Show>();
} }
public override async Task<ShowDE> Create(ShowDE obj) public override async Task<Show> Create(Show obj)
{ {
await base.Create(obj); await base.Create(obj);
_database.Entry(obj).State = EntityState.Added; _database.Entry(obj).State = EntityState.Added;
if (obj.GenreLinks != null)
{
foreach (GenreLink entry in obj.GenreLinks)
{
if (!(entry.Child is GenreDE))
entry.Child = new GenreDE(entry.Child);
_database.Entry(entry).State = EntityState.Added;
}
}
if (obj.People != null) if (obj.People != null)
foreach (PeopleRole entry in obj.People) foreach (PeopleRole entry in obj.People)
_database.Entry(entry).State = EntityState.Added; _database.Entry(entry).State = EntityState.Added;
@ -107,17 +97,16 @@ namespace Kyoo.Controllers
return obj; return obj;
} }
protected override async Task Validate(ShowDE resource) protected override async Task Validate(Show resource)
{ {
await base.Validate(resource); await base.Validate(resource);
if (ShouldValidate(resource.Studio)) if (ShouldValidate(resource.Studio))
resource.Studio = await _studios.CreateIfNotExists(resource.Studio, true); resource.Studio = await _studios.CreateIfNotExists(resource.Studio, true);
if (resource.GenreLinks != null) resource.Genres = await resource.Genres
foreach (GenreLink link in resource.GenreLinks) .SelectAsync(x => _genres.CreateIfNotExists(x, true))
if (ShouldValidate(link)) .ToListAsync();
link.Child = await _genres.CreateIfNotExists(link.Child, true);
if (resource.People != null) if (resource.People != null)
foreach (PeopleRole link in resource.People) foreach (PeopleRole link in resource.People)
@ -134,32 +123,30 @@ namespace Kyoo.Controllers
{ {
if (collectionID != null) if (collectionID != null)
{ {
// await _database.CollectionLinks.AddAsync(new CollectionLink {ParentID = collectionID.Value, ChildID = showID});
await _database.CollectionLinks.AddAsync(new CollectionLink {ParentID = collectionID.Value, ChildID = showID});
await _database.SaveIfNoDuplicates(); await _database.SaveIfNoDuplicates();
} }
if (libraryID != null) if (libraryID != null)
{ {
// await _database.LibraryLinks.AddAsync(new LibraryLink {LibraryID = libraryID.Value, ShowID = showID}); await _database.LibraryLinks.AddAsync(new LibraryLink {LibraryID = libraryID.Value, ShowID = showID});
await _database.SaveIfNoDuplicates(); await _database.SaveIfNoDuplicates();
} }
if (libraryID != null && collectionID != null) if (libraryID != null && collectionID != null)
{ {
// await _database.LibraryLinks.AddAsync(new LibraryLink {LibraryID = libraryID.Value, CollectionID = collectionID.Value}); await _database.LibraryLinks.AddAsync(new LibraryLink {LibraryID = libraryID.Value, CollectionID = collectionID.Value});
await _database.SaveIfNoDuplicates(); await _database.SaveIfNoDuplicates();
} }
} }
public override async Task Delete(ShowDE obj) public override async Task Delete(Show obj)
{ {
if (obj == null) if (obj == null)
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
if (obj.GenreLinks != null)
foreach (GenreLink entry in obj.GenreLinks)
_database.Entry(entry).State = EntityState.Deleted;
if (obj.People != null) if (obj.People != null)
foreach (PeopleRole entry in obj.People) foreach (PeopleRole entry in obj.People)
@ -169,14 +156,6 @@ namespace Kyoo.Controllers
foreach (MetadataID entry in obj.ExternalIDs) foreach (MetadataID entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Deleted; _database.Entry(entry).State = EntityState.Deleted;
if (obj.CollectionLinks != null)
foreach (CollectionLink entry in obj.CollectionLinks)
_database.Entry(entry).State = EntityState.Deleted;
if (obj.LibraryLinks != null)
foreach (LibraryLink entry in obj.LibraryLinks)
_database.Entry(entry).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
if (obj.Seasons != null) if (obj.Seasons != null)

View File

@ -19,7 +19,7 @@ namespace Kyoo.Controllers
_database = database; _database = database;
} }
public async Task<ICollection<Studio>> Search(string query) public override async Task<ICollection<Studio>> Search(string query)
{ {
return await _database.Studios return await _database.Studios
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%")) .Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))

View File

@ -73,7 +73,7 @@ namespace Kyoo.Controllers
&& x.IsForced == forced); && x.IsForced == forced);
} }
public Task<ICollection<Track>> Search(string query) public override Task<ICollection<Track>> Search(string query)
{ {
throw new InvalidOperationException("Tracks do not support the search method."); throw new InvalidOperationException("Tracks do not support the search method.");
} }

View File

@ -119,12 +119,6 @@ namespace Kyoo
modelBuilder.Entity<Episode>() modelBuilder.Entity<Episode>()
.HasIndex(x => new {x.ShowID, x.SeasonNumber, x.EpisodeNumber, x.AbsoluteNumber}) .HasIndex(x => new {x.ShowID, x.SeasonNumber, x.EpisodeNumber, x.AbsoluteNumber})
.IsUnique(); .IsUnique();
modelBuilder.Entity<LibraryLink>()
.HasIndex(x => new {x.LibraryID, x.ShowID})
.IsUnique();
modelBuilder.Entity<LibraryLink>()
.HasIndex(x => new {x.LibraryID, x.CollectionID})
.IsUnique();
} }
public override int SaveChanges() public override int SaveChanges()

View File

@ -1,20 +0,0 @@
namespace Kyoo.Models
{
public class CollectionLink : IResourceLink<Collection, Show>
{
public int ParentID { get; set; }
public virtual Collection Parent { get; set; }
public int ChildID { get; set; }
public virtual Show Child { get; set; }
public CollectionLink() { }
public CollectionLink(Collection parent, Show child)
{
Parent = parent;
ParentID = parent.ID;
Child = child;
ChildID = child.ID;
}
}
}

View File

@ -1,18 +0,0 @@
namespace Kyoo.Models
{
public class GenreLink : IResourceLink<Show, Genre>
{
public int ParentID { get; set; }
public virtual Show Parent { get; set; }
public int ChildID { get; set; }
public virtual Genre Child { get; set; }
public GenreLink() {}
public GenreLink(Show parent, Genre child)
{
Parent = parent;
Child = child;
}
}
}

View File

@ -1,27 +0,0 @@
namespace Kyoo.Models
{
public class LibraryLink
{
public int ID { get; set; }
public int LibraryID { get; set; }
public virtual Library Library { get; set; }
public int? ShowID { get; set; }
public virtual Show Show { get; set; }
public int? CollectionID { get; set; }
public virtual Collection Collection { get; set; }
public LibraryLink() { }
public LibraryLink(Library library, Show show)
{
Library = library;
Show = show;
}
public LibraryLink(Library library, Collection collection)
{
Library = library;
Collection = collection;
}
}
}

View File

@ -1,20 +0,0 @@
using Newtonsoft.Json;
namespace Kyoo.Models
{
public class ProviderLink : IResourceLink<Library, ProviderID>
{
[JsonIgnore] public int ParentID { get; set; }
[JsonIgnore] public virtual Library Parent { get; set; }
[JsonIgnore] public int ChildID { get; set; }
[JsonIgnore] public virtual ProviderID Child { get; set; }
public ProviderLink() { }
public ProviderLink(ProviderID child, Library parent)
{
Child = child;
Parent = parent;
}
}
}

View File

@ -1,33 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Kyoo.Models.Attributes;
namespace Kyoo.Models
{
public class CollectionDE : Collection
{
[SerializeIgnore] [NotMergable] public virtual ICollection<CollectionLink> Links { get; set; }
[ExpressionRewrite(nameof(Links), nameof(CollectionLink.Child))]
public override ICollection<Show> Shows
{
get => Links?.Select(x => x.Child).ToList();
set => Links = value?.Select(x => new CollectionLink(this, x)).ToList();
}
[SerializeIgnore] [NotMergable] public virtual ICollection<LibraryLink> LibraryLinks { get; set; }
[ExpressionRewrite(nameof(LibraryLinks), nameof(GenreLink.Child))]
public override ICollection<Library> Libraries
{
get => LibraryLinks?.Select(x => x.Library).ToList();
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this)).ToList();
}
public CollectionDE() {}
public CollectionDE(Collection collection)
{
Utility.Assign(this, collection);
}
}
}

View File

@ -1,25 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Kyoo.Models.Attributes;
namespace Kyoo.Models
{
public class GenreDE : Genre
{
[SerializeIgnore] [NotMergable] public virtual ICollection<GenreLink> Links { get; set; }
[ExpressionRewrite(nameof(Links), nameof(GenreLink.Child))]
[SerializeIgnore] [NotMergable] public override ICollection<Show> Shows
{
get => Links?.Select(x => x.Parent).ToList();
set => Links = value?.Select(x => new GenreLink(x, this)).ToList();
}
public GenreDE() {}
public GenreDE(Genre item)
{
Utility.Assign(this, item);
}
}
}

View File

@ -1,42 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Kyoo.Models.Attributes;
namespace Kyoo.Models
{
public class LibraryDE : Library
{
[EditableRelation] [SerializeIgnore] [NotMergable] public virtual ICollection<ProviderLink> ProviderLinks { get; set; }
[ExpressionRewrite(nameof(ProviderLinks), nameof(ProviderLink.Child))]
public override ICollection<ProviderID> Providers
{
get => ProviderLinks?.Select(x => x.Child).ToList();
set => ProviderLinks = value?.Select(x => new ProviderLink(x, this)).ToList();
}
[SerializeIgnore] [NotMergable] public virtual ICollection<LibraryLink> Links { get; set; }
[ExpressionRewrite(nameof(Links), nameof(LibraryLink.Show))]
public override ICollection<Show> Shows
{
get => Links?.Where(x => x.Show != null).Select(x => x.Show).ToList();
set => Links = Utility.MergeLists(
value?.Select(x => new LibraryLink(this, x)),
Links?.Where(x => x.Show == null))?.ToList();
}
[ExpressionRewrite(nameof(Links), nameof(LibraryLink.Collection))]
public override ICollection<Collection> Collections
{
get => Links?.Where(x => x.Collection != null).Select(x => x.Collection).ToList();
set => Links = Utility.MergeLists(
value?.Select(x => new LibraryLink(this, x)),
Links?.Where(x => x.Collection == null))?.ToList();
}
public LibraryDE() {}
public LibraryDE(Library item)
{
Utility.Assign(this, item);
}
}
}

View File

@ -1,40 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Kyoo.Models.Attributes;
namespace Kyoo.Models
{
public class ShowDE : Show
{
[EditableRelation] [SerializeIgnore] [NotMergable] public virtual ICollection<GenreLink> GenreLinks { get; set; }
[ExpressionRewrite(nameof(GenreLinks), nameof(GenreLink.Child))]
public override ICollection<Genre> Genres
{
get => GenreLinks?.Select(x => x.Child).ToList();
set => GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList();
}
[SerializeIgnore] [NotMergable] public virtual ICollection<LibraryLink> LibraryLinks { get; set; }
[ExpressionRewrite(nameof(LibraryLinks), nameof(LibraryLink.Library))]
public override ICollection<Library> Libraries
{
get => LibraryLinks?.Select(x => x.Library).ToList();
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this)).ToList();
}
[SerializeIgnore] [NotMergable] public virtual ICollection<CollectionLink> CollectionLinks { get; set; }
[ExpressionRewrite(nameof(CollectionLinks), nameof(CollectionLink.Parent))]
public override ICollection<Collection> Collections
{
get => CollectionLinks?.Select(x => x.Parent).ToList();
set => CollectionLinks = value?.Select(x => new CollectionLink(x, this)).ToList();
}
public ShowDE() {}
public ShowDE(Show show)
{
Utility.Assign(this, show);
}
}
}