diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index b78150f3..ce526a01 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -33,7 +33,8 @@ namespace Kyoo.Controllers Key = key; Descendant = descendant; - if (Key.Body is MemberExpression || + if (Key == null || + Key.Body is MemberExpression || Key.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)Key.Body).Operand is MemberExpression) return; diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs index fb03491a..84c79ffa 100644 --- a/Kyoo.Common/Utility.cs +++ b/Kyoo.Common/Utility.cs @@ -174,7 +174,7 @@ namespace Kyoo throw new ArgumentNullException(nameof(methodName)); if (type == null) throw new ArgumentNullException(nameof(type)); - MethodInfo method = owner.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + MethodInfo method = owner.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) throw new NullReferenceException($"A method named {methodName} could not be found on {owner.FullName}"); return method.MakeGenericMethod(type).Invoke(null, args?.ToArray()); @@ -192,7 +192,7 @@ namespace Kyoo throw new ArgumentNullException(nameof(methodName)); if (type == null) throw new ArgumentNullException(nameof(type)); - MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) throw new NullReferenceException($"A method named {methodName} could not be found on {instance.GetType().FullName}"); return method.MakeGenericMethod(type).Invoke(instance, args?.ToArray()); @@ -250,15 +250,19 @@ namespace Kyoo public static Task Cast(this Task task) { - return (Task)task; + return task.ContinueWith(x => (T)((dynamic)x).Result, + TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion); } - public static Expression Convert(this Expression expr) + public static Expression Convert([CanBeNull] this Expression expr) where T : Delegate { - if (expr is LambdaExpression lambda) - return new ExpressionConverter(lambda).VisitAndConvert(); - throw new ArgumentException("Can't convert a non lambda."); + return expr switch + { + null => null, + LambdaExpression lambda => new ExpressionConverter(lambda).VisitAndConvert(), + _ => throw new ArgumentException("Can't convert a non lambda.") + }; } private class ExpressionConverter : ExpressionVisitor diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.Designer.cs similarity index 83% rename from Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.Designer.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.Designer.cs index 0e398aef..35a902db 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.Designer.cs @@ -11,7 +11,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] - [Migration("20200804172021_Initial")] + [Migration("20200815231223_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -32,6 +32,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -49,7 +53,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Collections"); + b.ToTable("Collection"); + + b.HasDiscriminator("Discriminator").HasValue("Collection"); }); modelBuilder.Entity("Kyoo.Models.CollectionLink", b => @@ -59,14 +65,24 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("CollectionDEID") + .HasColumnType("integer"); + b.Property("CollectionID") .HasColumnType("integer"); + b.Property("ShowDEID") + .HasColumnType("integer"); + b.Property("ShowID") .HasColumnType("integer"); b.HasKey("ID"); + b.HasIndex("CollectionDEID"); + + b.HasIndex("ShowDEID"); + b.HasIndex("ShowID"); b.HasIndex("CollectionID", "ShowID") @@ -88,15 +104,15 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("EpisodeNumber") .HasColumnType("integer"); - b.Property("ImgPrimary") - .HasColumnType("text"); - b.Property("Overview") .HasColumnType("text"); b.Property("Path") .HasColumnType("text"); + b.Property("Poster") + .HasColumnType("text"); + b.Property("ReleaseDate") .HasColumnType("timestamp without time zone"); @@ -132,6 +148,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -143,7 +163,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Genres"); + b.ToTable("Genre"); + + b.HasDiscriminator("Discriminator").HasValue("Genre"); }); modelBuilder.Entity("Kyoo.Models.GenreLink", b => @@ -154,10 +176,20 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("GenreID") .HasColumnType("integer"); + b.Property("GenreDEID") + .HasColumnType("integer"); + + b.Property("ShowDEID") + .HasColumnType("integer"); + b.HasKey("ShowID", "GenreID"); + b.HasIndex("GenreDEID"); + b.HasIndex("GenreID"); + b.HasIndex("ShowDEID"); + b.ToTable("GenreLinks"); }); @@ -168,6 +200,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -182,7 +218,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Libraries"); + b.ToTable("Library"); + + b.HasDiscriminator("Discriminator").HasValue("Library"); }); modelBuilder.Entity("Kyoo.Models.LibraryLink", b => @@ -192,19 +230,34 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("CollectionDEID") + .HasColumnType("integer"); + b.Property("CollectionID") .HasColumnType("integer"); + b.Property("LibraryDEID") + .HasColumnType("integer"); + b.Property("LibraryID") .HasColumnType("integer"); + b.Property("ShowDEID") + .HasColumnType("integer"); + b.Property("ShowID") .HasColumnType("integer"); b.HasKey("ID"); + b.HasIndex("CollectionDEID"); + b.HasIndex("CollectionID"); + b.HasIndex("LibraryDEID"); + + b.HasIndex("ShowDEID"); + b.HasIndex("ShowID"); b.HasIndex("LibraryID", "CollectionID") @@ -283,7 +336,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("People"); }); - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + modelBuilder.Entity("Kyoo.Models.PeopleRole", b => { b.Property("ID") .ValueGeneratedOnAdd() @@ -342,6 +395,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("LibraryDEID") + .HasColumnType("integer"); + b.Property("LibraryID") .HasColumnType("integer"); @@ -350,6 +406,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasKey("ID"); + b.HasIndex("LibraryDEID"); + b.HasIndex("LibraryID"); b.HasIndex("ProviderID"); @@ -403,6 +461,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Backdrop") .HasColumnType("text"); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("EndYear") .HasColumnType("integer"); @@ -446,7 +508,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("StudioID"); - b.ToTable("Shows"); + b.ToTable("Show"); + + b.HasDiscriminator("Discriminator").HasValue("Show"); }); modelBuilder.Entity("Kyoo.Models.Studio", b => @@ -511,14 +575,50 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("Tracks"); }); + modelBuilder.Entity("Kyoo.Models.CollectionDE", b => + { + b.HasBaseType("Kyoo.Models.Collection"); + + b.HasDiscriminator().HasValue("CollectionDE"); + }); + + modelBuilder.Entity("Kyoo.Models.GenreDE", b => + { + b.HasBaseType("Kyoo.Models.Genre"); + + b.HasDiscriminator().HasValue("GenreDE"); + }); + + modelBuilder.Entity("Kyoo.Models.LibraryDE", b => + { + b.HasBaseType("Kyoo.Models.Library"); + + b.HasDiscriminator().HasValue("LibraryDE"); + }); + + modelBuilder.Entity("Kyoo.Models.ShowDE", b => + { + b.HasBaseType("Kyoo.Models.Show"); + + b.HasDiscriminator().HasValue("ShowDE"); + }); + modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { - b.HasOne("Kyoo.Models.Collection", "Collection") + b.HasOne("Kyoo.Models.CollectionDE", null) .WithMany("Links") + .HasForeignKey("CollectionDEID"); + + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() .HasForeignKey("CollectionID"); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("CollectionLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -539,14 +639,22 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.GenreLink", b => { - b.HasOne("Kyoo.Models.Genre", "Genre") + b.HasOne("Kyoo.Models.GenreDE", null) .WithMany("Links") + .HasForeignKey("GenreDEID"); + + b.HasOne("Kyoo.Models.Genre", "Genre") + .WithMany() .HasForeignKey("GenreID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("GenreLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -554,18 +662,30 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.LibraryLink", b => { - b.HasOne("Kyoo.Models.Collection", "Collection") + b.HasOne("Kyoo.Models.CollectionDE", null) .WithMany("LibraryLinks") + .HasForeignKey("CollectionDEID"); + + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() .HasForeignKey("CollectionID"); - b.HasOne("Kyoo.Models.Library", "Library") + b.HasOne("Kyoo.Models.LibraryDE", null) .WithMany("Links") + .HasForeignKey("LibraryDEID"); + + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany() .HasForeignKey("LibraryID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("LibraryLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID"); }); @@ -598,7 +718,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .OnDelete(DeleteBehavior.Cascade); }); - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + modelBuilder.Entity("Kyoo.Models.PeopleRole", b => { b.HasOne("Kyoo.Models.People", "People") .WithMany("Roles") @@ -615,8 +735,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderLink", b => { - b.HasOne("Kyoo.Models.Library", "Library") + b.HasOne("Kyoo.Models.LibraryDE", null) .WithMany("ProviderLinks") + .HasForeignKey("LibraryDEID"); + + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany() .HasForeignKey("LibraryID"); b.HasOne("Kyoo.Models.ProviderID", "Provider") diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.cs similarity index 76% rename from Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.cs index d94bb616..79d4b9a4 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200804172021_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200815231223_Initial.cs @@ -14,7 +14,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .Annotation("Npgsql:Enum:stream_type", "unknow,video,audio,subtitle"); migrationBuilder.CreateTable( - name: "Collections", + name: "Collection", columns: table => new { ID = table.Column(nullable: false) @@ -22,40 +22,43 @@ namespace Kyoo.Models.DatabaseMigrations.Internal Slug = table.Column(nullable: true), Name = table.Column(nullable: true), Poster = table.Column(nullable: true), - Overview = table.Column(nullable: true) + Overview = table.Column(nullable: true), + Discriminator = table.Column(nullable: false) }, constraints: table => { - table.PrimaryKey("PK_Collections", x => x.ID); + table.PrimaryKey("PK_Collection", x => x.ID); }); migrationBuilder.CreateTable( - name: "Genres", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - Slug = table.Column(nullable: true), - Name = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Genres", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Libraries", + name: "Genre", columns: table => new { ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), Slug = table.Column(nullable: true), Name = table.Column(nullable: true), - Paths = table.Column(type: "text[]", nullable: true) + Discriminator = table.Column(nullable: false) }, constraints: table => { - table.PrimaryKey("PK_Libraries", x => x.ID); + table.PrimaryKey("PK_Genre", x => x.ID); + }); + + migrationBuilder.CreateTable( + name: "Library", + columns: table => new + { + ID = table.Column(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Slug = table.Column(nullable: true), + Name = table.Column(nullable: true), + Paths = table.Column(type: "text[]", nullable: true), + Discriminator = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Library", x => x.ID); }); migrationBuilder.CreateTable( @@ -109,15 +112,22 @@ namespace Kyoo.Models.DatabaseMigrations.Internal ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), ProviderID = table.Column(nullable: false), - LibraryID = table.Column(nullable: true) + LibraryID = table.Column(nullable: true), + LibraryDEID = table.Column(nullable: true) }, constraints: table => { table.PrimaryKey("PK_ProviderLinks", x => x.ID); table.ForeignKey( - name: "FK_ProviderLinks_Libraries_LibraryID", + name: "FK_ProviderLinks_Library_LibraryDEID", + column: x => x.LibraryDEID, + principalTable: "Library", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ProviderLinks_Library_LibraryID", column: x => x.LibraryID, - principalTable: "Libraries", + principalTable: "Library", principalColumn: "ID", onDelete: ReferentialAction.Restrict); table.ForeignKey( @@ -129,7 +139,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal }); migrationBuilder.CreateTable( - name: "Shows", + name: "Show", columns: table => new { ID = table.Column(nullable: false) @@ -147,13 +157,14 @@ namespace Kyoo.Models.DatabaseMigrations.Internal Logo = table.Column(nullable: true), Backdrop = table.Column(nullable: true), IsMovie = table.Column(nullable: false), - StudioID = table.Column(nullable: true) + StudioID = table.Column(nullable: true), + Discriminator = table.Column(nullable: false) }, constraints: table => { - table.PrimaryKey("PK_Shows", x => x.ID); + table.PrimaryKey("PK_Show", x => x.ID); table.ForeignKey( - name: "FK_Shows_Studios_StudioID", + name: "FK_Show_Studios_StudioID", column: x => x.StudioID, principalTable: "Studios", principalColumn: "ID", @@ -167,21 +178,35 @@ namespace Kyoo.Models.DatabaseMigrations.Internal ID = table.Column(nullable: false) .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), CollectionID = table.Column(nullable: true), - ShowID = table.Column(nullable: false) + ShowID = table.Column(nullable: false), + CollectionDEID = table.Column(nullable: true), + ShowDEID = table.Column(nullable: true) }, constraints: table => { table.PrimaryKey("PK_CollectionLinks", x => x.ID); table.ForeignKey( - name: "FK_CollectionLinks_Collections_CollectionID", - column: x => x.CollectionID, - principalTable: "Collections", + name: "FK_CollectionLinks_Collection_CollectionDEID", + column: x => x.CollectionDEID, + principalTable: "Collection", principalColumn: "ID", onDelete: ReferentialAction.Restrict); table.ForeignKey( - name: "FK_CollectionLinks_Shows_ShowID", + name: "FK_CollectionLinks_Collection_CollectionID", + column: x => x.CollectionID, + principalTable: "Collection", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_CollectionLinks_Show_ShowDEID", + column: x => x.ShowDEID, + principalTable: "Show", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_CollectionLinks_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -191,21 +216,35 @@ namespace Kyoo.Models.DatabaseMigrations.Internal columns: table => new { ShowID = table.Column(nullable: false), - GenreID = table.Column(nullable: false) + GenreID = table.Column(nullable: false), + GenreDEID = table.Column(nullable: true), + ShowDEID = table.Column(nullable: true) }, constraints: table => { table.PrimaryKey("PK_GenreLinks", x => new { x.ShowID, x.GenreID }); table.ForeignKey( - name: "FK_GenreLinks_Genres_GenreID", + name: "FK_GenreLinks_Genre_GenreDEID", + column: x => x.GenreDEID, + principalTable: "Genre", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_GenreLinks_Genre_GenreID", column: x => x.GenreID, - principalTable: "Genres", + principalTable: "Genre", principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_GenreLinks_Shows_ShowID", + name: "FK_GenreLinks_Show_ShowDEID", + column: x => x.ShowDEID, + principalTable: "Show", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_GenreLinks_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -218,27 +257,48 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), LibraryID = table.Column(nullable: false), ShowID = table.Column(nullable: true), - CollectionID = table.Column(nullable: true) + CollectionID = table.Column(nullable: true), + CollectionDEID = table.Column(nullable: true), + LibraryDEID = table.Column(nullable: true), + ShowDEID = table.Column(nullable: true) }, constraints: table => { table.PrimaryKey("PK_LibraryLinks", x => x.ID); table.ForeignKey( - name: "FK_LibraryLinks_Collections_CollectionID", - column: x => x.CollectionID, - principalTable: "Collections", + name: "FK_LibraryLinks_Collection_CollectionDEID", + column: x => x.CollectionDEID, + principalTable: "Collection", principalColumn: "ID", onDelete: ReferentialAction.Restrict); table.ForeignKey( - name: "FK_LibraryLinks_Libraries_LibraryID", + name: "FK_LibraryLinks_Collection_CollectionID", + column: x => x.CollectionID, + principalTable: "Collection", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LibraryLinks_Library_LibraryDEID", + column: x => x.LibraryDEID, + principalTable: "Library", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LibraryLinks_Library_LibraryID", column: x => x.LibraryID, - principalTable: "Libraries", + principalTable: "Library", principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_LibraryLinks_Shows_ShowID", + name: "FK_LibraryLinks_Show_ShowDEID", + column: x => x.ShowDEID, + principalTable: "Show", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LibraryLinks_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Restrict); }); @@ -264,9 +324,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_PeopleRoles_Shows_ShowID", + name: "FK_PeopleRoles_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -288,9 +348,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal { table.PrimaryKey("PK_Seasons", x => x.ID); table.ForeignKey( - name: "FK_Seasons_Shows_ShowID", + name: "FK_Seasons_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -311,7 +371,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal Overview = table.Column(nullable: true), ReleaseDate = table.Column(nullable: true), Runtime = table.Column(nullable: false), - ImgPrimary = table.Column(nullable: true) + Poster = table.Column(nullable: true) }, constraints: table => { @@ -323,9 +383,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal principalColumn: "ID", onDelete: ReferentialAction.Restrict); table.ForeignKey( - name: "FK_Episodes_Shows_ShowID", + name: "FK_Episodes_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -372,9 +432,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal principalColumn: "ID", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_MetadataIds_Shows_ShowID", + name: "FK_MetadataIds_Show_ShowID", column: x => x.ShowID, - principalTable: "Shows", + principalTable: "Show", principalColumn: "ID", onDelete: ReferentialAction.Cascade); }); @@ -406,6 +466,22 @@ namespace Kyoo.Models.DatabaseMigrations.Internal onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_Collection_Slug", + table: "Collection", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_CollectionLinks_CollectionDEID", + table: "CollectionLinks", + column: "CollectionDEID"); + + migrationBuilder.CreateIndex( + name: "IX_CollectionLinks_ShowDEID", + table: "CollectionLinks", + column: "ShowDEID"); + migrationBuilder.CreateIndex( name: "IX_CollectionLinks_ShowID", table: "CollectionLinks", @@ -417,12 +493,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal columns: new[] { "CollectionID", "ShowID" }, unique: true); - migrationBuilder.CreateIndex( - name: "IX_Collections_Slug", - table: "Collections", - column: "Slug", - unique: true); - migrationBuilder.CreateIndex( name: "IX_Episodes_SeasonID", table: "Episodes", @@ -434,28 +504,53 @@ namespace Kyoo.Models.DatabaseMigrations.Internal columns: new[] { "ShowID", "SeasonNumber", "EpisodeNumber", "AbsoluteNumber" }, unique: true); + migrationBuilder.CreateIndex( + name: "IX_Genre_Slug", + table: "Genre", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_GenreLinks_GenreDEID", + table: "GenreLinks", + column: "GenreDEID"); + migrationBuilder.CreateIndex( name: "IX_GenreLinks_GenreID", table: "GenreLinks", column: "GenreID"); migrationBuilder.CreateIndex( - name: "IX_Genres_Slug", - table: "Genres", + name: "IX_GenreLinks_ShowDEID", + table: "GenreLinks", + column: "ShowDEID"); + + migrationBuilder.CreateIndex( + name: "IX_Library_Slug", + table: "Library", column: "Slug", unique: true); migrationBuilder.CreateIndex( - name: "IX_Libraries_Slug", - table: "Libraries", - column: "Slug", - unique: true); + name: "IX_LibraryLinks_CollectionDEID", + table: "LibraryLinks", + column: "CollectionDEID"); migrationBuilder.CreateIndex( name: "IX_LibraryLinks_CollectionID", table: "LibraryLinks", column: "CollectionID"); + migrationBuilder.CreateIndex( + name: "IX_LibraryLinks_LibraryDEID", + table: "LibraryLinks", + column: "LibraryDEID"); + + migrationBuilder.CreateIndex( + name: "IX_LibraryLinks_ShowDEID", + table: "LibraryLinks", + column: "ShowDEID"); + migrationBuilder.CreateIndex( name: "IX_LibraryLinks_ShowID", table: "LibraryLinks", @@ -514,6 +609,11 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table: "PeopleRoles", column: "ShowID"); + migrationBuilder.CreateIndex( + name: "IX_ProviderLinks_LibraryDEID", + table: "ProviderLinks", + column: "LibraryDEID"); + migrationBuilder.CreateIndex( name: "IX_ProviderLinks_LibraryID", table: "ProviderLinks", @@ -537,14 +637,14 @@ namespace Kyoo.Models.DatabaseMigrations.Internal unique: true); migrationBuilder.CreateIndex( - name: "IX_Shows_Slug", - table: "Shows", + name: "IX_Show_Slug", + table: "Show", column: "Slug", unique: true); migrationBuilder.CreateIndex( - name: "IX_Shows_StudioID", - table: "Shows", + name: "IX_Show_StudioID", + table: "Show", column: "StudioID"); migrationBuilder.CreateIndex( @@ -583,16 +683,16 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Tracks"); migrationBuilder.DropTable( - name: "Genres"); + name: "Genre"); migrationBuilder.DropTable( - name: "Collections"); + name: "Collection"); migrationBuilder.DropTable( name: "People"); migrationBuilder.DropTable( - name: "Libraries"); + name: "Library"); migrationBuilder.DropTable( name: "Providers"); @@ -604,7 +704,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "Seasons"); migrationBuilder.DropTable( - name: "Shows"); + name: "Show"); migrationBuilder.DropTable( name: "Studios"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index b7c0e3cf..4bc4bc19 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -30,6 +30,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -47,7 +51,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Collections"); + b.ToTable("Collection"); + + b.HasDiscriminator("Discriminator").HasValue("Collection"); }); modelBuilder.Entity("Kyoo.Models.CollectionLink", b => @@ -57,14 +63,24 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("CollectionDEID") + .HasColumnType("integer"); + b.Property("CollectionID") .HasColumnType("integer"); + b.Property("ShowDEID") + .HasColumnType("integer"); + b.Property("ShowID") .HasColumnType("integer"); b.HasKey("ID"); + b.HasIndex("CollectionDEID"); + + b.HasIndex("ShowDEID"); + b.HasIndex("ShowID"); b.HasIndex("CollectionID", "ShowID") @@ -86,15 +102,15 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("EpisodeNumber") .HasColumnType("integer"); - b.Property("ImgPrimary") - .HasColumnType("text"); - b.Property("Overview") .HasColumnType("text"); b.Property("Path") .HasColumnType("text"); + b.Property("Poster") + .HasColumnType("text"); + b.Property("ReleaseDate") .HasColumnType("timestamp without time zone"); @@ -130,6 +146,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -141,7 +161,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Genres"); + b.ToTable("Genre"); + + b.HasDiscriminator("Discriminator").HasValue("Genre"); }); modelBuilder.Entity("Kyoo.Models.GenreLink", b => @@ -152,10 +174,20 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("GenreID") .HasColumnType("integer"); + b.Property("GenreDEID") + .HasColumnType("integer"); + + b.Property("ShowDEID") + .HasColumnType("integer"); + b.HasKey("ShowID", "GenreID"); + b.HasIndex("GenreDEID"); + b.HasIndex("GenreID"); + b.HasIndex("ShowDEID"); + b.ToTable("GenreLinks"); }); @@ -166,6 +198,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("Name") .HasColumnType("text"); @@ -180,7 +216,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("Slug") .IsUnique(); - b.ToTable("Libraries"); + b.ToTable("Library"); + + b.HasDiscriminator("Discriminator").HasValue("Library"); }); modelBuilder.Entity("Kyoo.Models.LibraryLink", b => @@ -190,19 +228,34 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("CollectionDEID") + .HasColumnType("integer"); + b.Property("CollectionID") .HasColumnType("integer"); + b.Property("LibraryDEID") + .HasColumnType("integer"); + b.Property("LibraryID") .HasColumnType("integer"); + b.Property("ShowDEID") + .HasColumnType("integer"); + b.Property("ShowID") .HasColumnType("integer"); b.HasKey("ID"); + b.HasIndex("CollectionDEID"); + b.HasIndex("CollectionID"); + b.HasIndex("LibraryDEID"); + + b.HasIndex("ShowDEID"); + b.HasIndex("ShowID"); b.HasIndex("LibraryID", "CollectionID") @@ -281,7 +334,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("People"); }); - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + modelBuilder.Entity("Kyoo.Models.PeopleRole", b => { b.Property("ID") .ValueGeneratedOnAdd() @@ -340,6 +393,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property("LibraryDEID") + .HasColumnType("integer"); + b.Property("LibraryID") .HasColumnType("integer"); @@ -348,6 +404,8 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasKey("ID"); + b.HasIndex("LibraryDEID"); + b.HasIndex("LibraryID"); b.HasIndex("ProviderID"); @@ -401,6 +459,10 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.Property("Backdrop") .HasColumnType("text"); + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + b.Property("EndYear") .HasColumnType("integer"); @@ -444,7 +506,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.HasIndex("StudioID"); - b.ToTable("Shows"); + b.ToTable("Show"); + + b.HasDiscriminator("Discriminator").HasValue("Show"); }); modelBuilder.Entity("Kyoo.Models.Studio", b => @@ -509,14 +573,50 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("Tracks"); }); + modelBuilder.Entity("Kyoo.Models.CollectionDE", b => + { + b.HasBaseType("Kyoo.Models.Collection"); + + b.HasDiscriminator().HasValue("CollectionDE"); + }); + + modelBuilder.Entity("Kyoo.Models.GenreDE", b => + { + b.HasBaseType("Kyoo.Models.Genre"); + + b.HasDiscriminator().HasValue("GenreDE"); + }); + + modelBuilder.Entity("Kyoo.Models.LibraryDE", b => + { + b.HasBaseType("Kyoo.Models.Library"); + + b.HasDiscriminator().HasValue("LibraryDE"); + }); + + modelBuilder.Entity("Kyoo.Models.ShowDE", b => + { + b.HasBaseType("Kyoo.Models.Show"); + + b.HasDiscriminator().HasValue("ShowDE"); + }); + modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { - b.HasOne("Kyoo.Models.Collection", "Collection") + b.HasOne("Kyoo.Models.CollectionDE", null) .WithMany("Links") + .HasForeignKey("CollectionDEID"); + + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() .HasForeignKey("CollectionID"); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("CollectionLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -537,14 +637,22 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.GenreLink", b => { - b.HasOne("Kyoo.Models.Genre", "Genre") + b.HasOne("Kyoo.Models.GenreDE", null) .WithMany("Links") + .HasForeignKey("GenreDEID"); + + b.HasOne("Kyoo.Models.Genre", "Genre") + .WithMany() .HasForeignKey("GenreID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("GenreLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -552,18 +660,30 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.LibraryLink", b => { - b.HasOne("Kyoo.Models.Collection", "Collection") + b.HasOne("Kyoo.Models.CollectionDE", null) .WithMany("LibraryLinks") + .HasForeignKey("CollectionDEID"); + + b.HasOne("Kyoo.Models.Collection", "Collection") + .WithMany() .HasForeignKey("CollectionID"); - b.HasOne("Kyoo.Models.Library", "Library") + b.HasOne("Kyoo.Models.LibraryDE", null) .WithMany("Links") + .HasForeignKey("LibraryDEID"); + + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany() .HasForeignKey("LibraryID") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Kyoo.Models.Show", "Show") + b.HasOne("Kyoo.Models.ShowDE", null) .WithMany("LibraryLinks") + .HasForeignKey("ShowDEID"); + + b.HasOne("Kyoo.Models.Show", "Show") + .WithMany() .HasForeignKey("ShowID"); }); @@ -596,7 +716,7 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .OnDelete(DeleteBehavior.Cascade); }); - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => + modelBuilder.Entity("Kyoo.Models.PeopleRole", b => { b.HasOne("Kyoo.Models.People", "People") .WithMany("Roles") @@ -613,8 +733,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder.Entity("Kyoo.Models.ProviderLink", b => { - b.HasOne("Kyoo.Models.Library", "Library") + b.HasOne("Kyoo.Models.LibraryDE", null) .WithMany("ProviderLinks") + .HasForeignKey("LibraryDEID"); + + b.HasOne("Kyoo.Models.Library", "Library") + .WithMany() .HasForeignKey("LibraryID"); b.HasOne("Kyoo.Models.ProviderID", "Provider") diff --git a/Kyoo/Models/Resources/CollectionDE.cs b/Kyoo/Models/Resources/CollectionDE.cs index e54bd0ce..f21411b3 100644 --- a/Kyoo/Models/Resources/CollectionDE.cs +++ b/Kyoo/Models/Resources/CollectionDE.cs @@ -10,7 +10,7 @@ namespace Kyoo.Models public override IEnumerable Shows { get => Links.Select(x => x.Show); - set => Links = value.Select(x => new CollectionLink(this, x)); + set => Links = value?.Select(x => new CollectionLink(this, x)); } [NotMergable] public virtual IEnumerable LibraryLinks { get; set; }