This commit is contained in:
Zoe Roux 2020-06-23 03:10:40 +02:00
commit d3a126bf03
21 changed files with 588 additions and 79 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Kyoo.Models;
@ -15,7 +16,17 @@ namespace Kyoo.Controllers
Task<int> Create([NotNull] T obj);
Task<int> CreateIfNotExists([NotNull] T obj);
Task Edit([NotNull] T edited, bool resetOld);
Task Delete(T obj);
Task Delete(int id);
Task Delete(string slug);
Task Delete([NotNull] T obj);
Task DeleteRange(params T[] objs) => DeleteRange(objs.AsEnumerable());
Task DeleteRange(IEnumerable<T> objs);
Task DeleteRange(params int[] ids) => DeleteRange(ids.AsEnumerable());
Task DeleteRange(IEnumerable<int> ids);
Task DeleteRange(params string[] slugs) => DeleteRange(slugs.AsEnumerable());
Task DeleteRange(IEnumerable<string> slugs);
}
public interface IShowRepository : IRepository<Show>
@ -27,6 +38,7 @@ namespace Kyoo.Controllers
public interface ISeasonRepository : IRepository<Season>
{
Task<Season> Get(string showSlug, int seasonNumber);
Task Delete(string showSlug, int seasonNumber);
Task<ICollection<Season>> GetSeasons(int showID);
Task<ICollection<Season>> GetSeasons(string showSlug);
@ -35,6 +47,7 @@ namespace Kyoo.Controllers
public interface IEpisodeRepository : IRepository<Episode>
{
Task<Episode> Get(string showSlug, int seasonNumber, int episodeNumber);
Task Delete(string showSlug, int seasonNumber, int episodeNumber);
Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber);
Task<ICollection<Episode>> GetEpisodes(string showSlug, int seasonNumber);

View File

@ -20,6 +20,14 @@ namespace Kyoo.Models
set => Links = value.Select(x => new CollectionLink(this, x));
}
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
[NotMergable] [JsonIgnore] public IEnumerable<Library> Libraries
{
get => LibraryLinks?.Select(x => x.Library);
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
}
public Collection() { }
public Collection(string slug, string name, string overview, string imgPrimary)

View File

@ -1,4 +1,7 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using Kyoo.Models.Attributes;
using Newtonsoft.Json;
namespace Kyoo.Models
{
@ -8,7 +11,13 @@ namespace Kyoo.Models
public string Slug { get; set; }
public string Name { get; set; }
// public IEnumerable<Show> Shows { get; set; }
[NotMergable] [JsonIgnore] public virtual IEnumerable<GenreLink> Links { get; set; }
[NotMergable] [JsonIgnore] public IEnumerable<Show> Shows
{
get => Links.Select(x => x.Show);
set => Links = value?.Select(x => new GenreLink(x, this));
}
public Genre() {}

View File

@ -42,6 +42,22 @@ namespace Kyoo.Models
[JsonIgnore] public virtual IEnumerable<Season> Seasons { get; set; }
[JsonIgnore] public virtual IEnumerable<Episode> Episodes { get; set; }
[NotMergable] [JsonIgnore] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
[NotMergable] [JsonIgnore] public IEnumerable<Library> Libraries
{
get => LibraryLinks?.Select(x => x.Library);
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));
}
[NotMergable] [JsonIgnore] public virtual IEnumerable<CollectionLink> CollectionLinks { get; set; }
[NotMergable] [JsonIgnore] public IEnumerable<Collection> Collections
{
get => CollectionLinks.Select(x => x.Collection);
set => CollectionLinks = value?.Select(x => new CollectionLink(x, this));
}
public Show() { }
public Show(string slug,

View File

@ -111,10 +111,49 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
Collection obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Collection obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Collection obj)
{
_database.Collections.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_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();
}
public async Task DeleteRange(IEnumerable<Collection> objs)
{
foreach (Collection obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -12,6 +12,7 @@ namespace Kyoo.Controllers
{
private readonly DatabaseContext _database;
private readonly IProviderRepository _providers;
// private readonly ITrackRepository _tracks;
public EpisodeRepository(DatabaseContext database, IProviderRepository providers)
@ -83,6 +84,8 @@ namespace Kyoo.Controllers
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Added;
// Since Episodes & Tracks are on the same DB, using a single commit is quicker.
if (obj.Tracks != null)
foreach (Track entry in obj.Tracks)
_database.Entry(entry).State = EntityState.Added;
@ -99,6 +102,16 @@ namespace Kyoo.Controllers
throw new DuplicatedItemException($"Trying to insert a duplicated episode (slug {obj.Slug} already exists).");
throw;
}
// Since Episodes & Tracks are on the same DB, using a single commit is quicker.
/*if (obj.Tracks != null)
* foreach (Track track in obj.Tracks)
* {
* track.EpisodeID = obj.ID;
* await _tracks.Create(track);
* }
*/
return obj.ID;
}
@ -153,12 +166,6 @@ namespace Kyoo.Controllers
}
}
public async Task Delete(Episode obj)
{
_database.Episodes.Remove(obj);
await _database.SaveChangesAsync();
}
public async Task<ICollection<Episode>> GetEpisodes(int showID, int seasonNumber)
{
return await _database.Episodes.Where(x => x.ShowID == showID
@ -175,5 +182,54 @@ namespace Kyoo.Controllers
{
return await _database.Episodes.Where(x => x.SeasonID == seasonID).ToListAsync();
}
public async Task Delete(int id)
{
Episode obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Episode obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(string showSlug, int seasonNumber, int episodeNumber)
{
Episode obj = await Get(showSlug, seasonNumber, episodeNumber);
await Delete(obj);
}
public async Task Delete(Episode obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Deleted;
// Since Tracks & Episodes are on the same database and handled by dotnet-ef, we can't use the repository to delete them.
await _database.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<Episode> objs)
{
foreach (Episode obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -56,7 +56,7 @@ namespace Kyoo.Controllers
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await _database.Genres.AddAsync(obj);
_database.Entry(obj).State = EntityState.Added;
try
{
@ -111,10 +111,46 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
Genre obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Genre obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Genre obj)
{
_database.Genres.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_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();
}
public async Task DeleteRange(IEnumerable<Genre> objs)
{
foreach (Genre obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -124,10 +124,49 @@ namespace Kyoo.Controllers
link.ProviderID = await _providers.CreateIfNotExists(link.Provider);
}
public async Task Delete(int id)
{
Library obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Library obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Library obj)
{
_database.Libraries.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_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();
}
public async Task DeleteRange(IEnumerable<Library> objs)
{
foreach (Library obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -123,10 +123,49 @@ namespace Kyoo.Controllers
link.ProviderID = await _providers.CreateIfNotExists(link.Provider);
}
public async Task Delete(int id)
{
People obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
People obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(People obj)
{
_database.Peoples.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Deleted;
if (obj.Roles != null)
foreach (PeopleLink link in obj.Roles)
_database.Entry(link).State = EntityState.Deleted;
await _database.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<People> objs)
{
foreach (People obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -110,10 +110,44 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
ProviderID obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
ProviderID obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(ProviderID obj)
{
_database.Providers.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
// TODO handle ExternalID deletion when they refer to this providerID.
await _database.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<ProviderID> objs)
{
foreach (ProviderID obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -12,12 +12,14 @@ namespace Kyoo.Controllers
{
private readonly DatabaseContext _database;
private readonly IProviderRepository _providers;
private readonly IEpisodeRepository _episodes;
public SeasonRepository(DatabaseContext database, IProviderRepository providers)
public SeasonRepository(DatabaseContext database, IProviderRepository providers, IEpisodeRepository episodes)
{
_database = database;
_providers = providers;
_episodes = episodes;
}
public void Dispose()
@ -142,12 +144,6 @@ namespace Kyoo.Controllers
}
}
public async Task Delete(Season obj)
{
_database.Seasons.Remove(obj);
await _database.SaveChangesAsync();
}
public async Task<ICollection<Season>> GetSeasons(int showID)
{
return await _database.Seasons.Where(x => x.ShowID == showID).ToListAsync();
@ -157,5 +153,58 @@ namespace Kyoo.Controllers
{
return await _database.Seasons.Where(x => x.Show.Slug == showSlug).ToListAsync();
}
public async Task Delete(int id)
{
Season obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Season obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(string showSlug, int seasonNumber)
{
Season obj = await Get(showSlug, seasonNumber);
await Delete(obj);
}
public async Task Delete(Season obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)
_database.Entry(entry).State = EntityState.Deleted;
await _database.SaveChangesAsync();
if (obj.Episodes != null)
await _episodes.DeleteRange(obj.Episodes);
}
public async Task DeleteRange(IEnumerable<Season> objs)
{
foreach (Season obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -15,18 +15,24 @@ namespace Kyoo.Controllers
private readonly IPeopleRepository _people;
private readonly IGenreRepository _genres;
private readonly IProviderRepository _providers;
private readonly ISeasonRepository _seasons;
private readonly IEpisodeRepository _episodes;
public ShowRepository(DatabaseContext database,
IStudioRepository studios,
IPeopleRepository people,
IGenreRepository genres,
IProviderRepository providers)
IProviderRepository providers,
ISeasonRepository seasons,
IEpisodeRepository episodes)
{
_database = database;
_studios = studios;
_people = people;
_genres = genres;
_providers = providers;
_seasons = seasons;
_episodes = episodes;
}
public void Dispose()
@ -40,19 +46,19 @@ namespace Kyoo.Controllers
await Task.WhenAll(_database.DisposeAsync().AsTask(), _studios.DisposeAsync().AsTask());
}
public async Task<Show> Get(int id)
public Task<Show> Get(int id)
{
return await _database.Shows.FirstOrDefaultAsync(x => x.ID == id);
return _database.Shows.FirstOrDefaultAsync(x => x.ID == id);
}
public async Task<Show> Get(string slug)
public Task<Show> Get(string slug)
{
return await _database.Shows.FirstOrDefaultAsync(x => x.Slug == slug);
return _database.Shows.FirstOrDefaultAsync(x => x.Slug == slug);
}
public async Task<Show> GetByPath(string path)
public Task<Show> GetByPath(string path)
{
return await _database.Shows.FirstOrDefaultAsync(x => x.Path == path);
return _database.Shows.FirstOrDefaultAsync(x => x.Path == path);
}
public async Task<ICollection<Show>> Search(string query)
@ -145,29 +151,17 @@ namespace Kyoo.Controllers
obj.StudioID = await _studios.CreateIfNotExists(obj.Studio);
if (obj.GenreLinks != null)
{
foreach (GenreLink link in obj.GenreLinks)
link.GenreID = await _genres.CreateIfNotExists(link.Genre);
}
if (obj.People != null)
{
foreach (PeopleLink link in obj.People)
link.PeopleID = await _people.CreateIfNotExists(link.People);
}
if (obj.ExternalIDs != null)
{
foreach (MetadataID link in obj.ExternalIDs)
link.ProviderID = await _providers.CreateIfNotExists(link.Provider);
}
}
public async Task Delete(Show show)
{
_database.Shows.Remove(show);
await _database.SaveChangesAsync();
}
public async Task AddShowLink(int showID, int? libraryID, int? collectionID)
{
@ -191,5 +185,71 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
Show obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Show obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Show obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_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)
foreach (PeopleLink entry in obj.People)
_database.Entry(entry).State = EntityState.Deleted;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)
_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();
if (obj.Seasons != null)
await _seasons.DeleteRange(obj.Seasons);
if (obj.Episodes != null)
await _episodes.DeleteRange(obj.Episodes);
}
public async Task DeleteRange(IEnumerable<Show> objs)
{
foreach (Show obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -109,10 +109,47 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
Studio obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Studio obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Studio obj)
{
_database.Studios.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
// Using Dotnet-EF change discovery service to remove references to this studio on shows.
foreach (Show show in obj.Shows)
show.StudioID = null;
await _database.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<Studio> objs)
{
foreach (Studio obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -99,10 +99,43 @@ namespace Kyoo.Controllers
await _database.SaveChangesAsync();
}
public async Task Delete(int id)
{
Track obj = await Get(id);
await Delete(obj);
}
public async Task Delete(string slug)
{
Track obj = await Get(slug);
await Delete(obj);
}
public async Task Delete(Track obj)
{
_database.Tracks.Remove(obj);
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted;
await _database.SaveChangesAsync();
}
public async Task DeleteRange(IEnumerable<Track> objs)
{
foreach (Track obj in objs)
await Delete(obj);
}
public async Task DeleteRange(IEnumerable<int> ids)
{
foreach (int id in ids)
await Delete(id);
}
public async Task DeleteRange(IEnumerable<string> slugs)
{
foreach (string slug in slugs)
await Delete(slug);
}
}
}

View File

@ -113,16 +113,40 @@ namespace Kyoo
.Ignore(x => x.Providers);
modelBuilder.Entity<Collection>()
.Ignore(x => x.Shows);
.Ignore(x => x.Shows)
.Ignore(x => x.Libraries);
modelBuilder.Entity<Show>()
.Ignore(x => x.Genres);
.Ignore(x => x.Genres)
.Ignore(x => x.Libraries)
.Ignore(x => x.Collections);
modelBuilder.Entity<PeopleLink>()
.Ignore(x => x.Slug)
.Ignore(x => x.Name)
.Ignore(x => x.ExternalIDs);
modelBuilder.Entity<Genre>()
.Ignore(x => x.Shows);
modelBuilder.Entity<MetadataID>()
.HasOne(x => x.Show)
.WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>()
.HasOne(x => x.Season)
.WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>()
.HasOne(x => x.Episode)
.WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MetadataID>()
.HasOne(x => x.People)
.WithMany(x => x.ExternalIDs)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Collection>()
.HasIndex(x => x.Slug)

View File

@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Kyoo.Models.DatabaseMigrations.Internal
{
[DbContext(typeof(DatabaseContext))]
[Migration("20200618133537_Initial")]
[Migration("20200623000428_Initial")]
partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -506,7 +506,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
.HasForeignKey("CollectionID");
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany()
.WithMany("CollectionLinks")
.HasForeignKey("ShowID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -528,7 +528,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
modelBuilder.Entity("Kyoo.Models.GenreLink", b =>
{
b.HasOne("Kyoo.Models.Genre", "Genre")
.WithMany()
.WithMany("Links")
.HasForeignKey("GenreID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -543,7 +543,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
modelBuilder.Entity("Kyoo.Models.LibraryLink", b =>
{
b.HasOne("Kyoo.Models.Collection", "Collection")
.WithMany()
.WithMany("LibraryLinks")
.HasForeignKey("CollectionID");
b.HasOne("Kyoo.Models.Library", "Library")
@ -553,7 +553,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
.IsRequired();
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany()
.WithMany("LibraryLinks")
.HasForeignKey("ShowID");
});
@ -561,11 +561,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
{
b.HasOne("Kyoo.Models.Episode", "Episode")
.WithMany("ExternalIDs")
.HasForeignKey("EpisodeID");
.HasForeignKey("EpisodeID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.People", "People")
.WithMany("ExternalIDs")
.HasForeignKey("PeopleID");
.HasForeignKey("PeopleID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.ProviderID", "Provider")
.WithMany()
@ -575,11 +577,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
b.HasOne("Kyoo.Models.Season", "Season")
.WithMany("ExternalIDs")
.HasForeignKey("SeasonID");
.HasForeignKey("SeasonID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany("ExternalIDs")
.HasForeignKey("ShowID");
.HasForeignKey("ShowID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Kyoo.Models.PeopleLink", b =>

View File

@ -347,13 +347,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
column: x => x.EpisodeID,
principalTable: "Episodes",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_MetadataIds_Peoples_PeopleID",
column: x => x.PeopleID,
principalTable: "Peoples",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_MetadataIds_Providers_ProviderID",
column: x => x.ProviderID,
@ -365,13 +365,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
column: x => x.SeasonID,
principalTable: "Seasons",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_MetadataIds_Shows_ShowID",
column: x => x.ShowID,
principalTable: "Shows",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(

View File

@ -504,7 +504,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
.HasForeignKey("CollectionID");
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany()
.WithMany("CollectionLinks")
.HasForeignKey("ShowID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -526,7 +526,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
modelBuilder.Entity("Kyoo.Models.GenreLink", b =>
{
b.HasOne("Kyoo.Models.Genre", "Genre")
.WithMany()
.WithMany("Links")
.HasForeignKey("GenreID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -541,7 +541,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
modelBuilder.Entity("Kyoo.Models.LibraryLink", b =>
{
b.HasOne("Kyoo.Models.Collection", "Collection")
.WithMany()
.WithMany("LibraryLinks")
.HasForeignKey("CollectionID");
b.HasOne("Kyoo.Models.Library", "Library")
@ -551,7 +551,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
.IsRequired();
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany()
.WithMany("LibraryLinks")
.HasForeignKey("ShowID");
});
@ -559,11 +559,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
{
b.HasOne("Kyoo.Models.Episode", "Episode")
.WithMany("ExternalIDs")
.HasForeignKey("EpisodeID");
.HasForeignKey("EpisodeID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.People", "People")
.WithMany("ExternalIDs")
.HasForeignKey("PeopleID");
.HasForeignKey("PeopleID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.ProviderID", "Provider")
.WithMany()
@ -573,11 +575,13 @@ namespace Kyoo.Models.DatabaseMigrations.Internal
b.HasOne("Kyoo.Models.Season", "Season")
.WithMany("ExternalIDs")
.HasForeignKey("SeasonID");
.HasForeignKey("SeasonID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("Kyoo.Models.Show", "Show")
.WithMany("ExternalIDs")
.HasForeignKey("ShowID");
.HasForeignKey("ShowID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Kyoo.Models.PeopleLink", b =>

View File

@ -46,8 +46,8 @@ namespace Kyoo
services.AddDbContext<DatabaseContext>(options =>
{
options.UseLazyLoadingProxies()
.UseNpgsql(_configuration.GetConnectionString("Database"))
.EnableSensitiveDataLogging();
.UseNpgsql(_configuration.GetConnectionString("Database"));
// .EnableSensitiveDataLogging()
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
}, ServiceLifetime.Transient);

View File

@ -58,6 +58,11 @@ namespace Kyoo.Controllers
using IServiceScope serviceScope = _serviceProvider.CreateScope();
await using ILibraryManager libraryManager = serviceScope.ServiceProvider.GetService<ILibraryManager>();
foreach (Show show in await libraryManager.GetShows())
if (!Directory.Exists(show.Path))
await libraryManager.DeleteShow(show);
ICollection<Episode> episodes = await libraryManager.GetEpisodes();
ICollection<Library> libraries = argument == null
? await libraryManager.GetLibraries()
@ -173,6 +178,10 @@ namespace Kyoo.Controllers
await libraryManager.AddShowLink(show, library, collection);
Console.WriteLine($"Episode at {path} registered.");
}
catch (DuplicatedItemException ex)
{
await Console.Error.WriteLineAsync($"{path}: {ex.Message}");
}
catch (Exception ex)
{
await Console.Error.WriteLineAsync($"Unknown exception thrown while registering episode at {path}." +