Add project files.

This commit is contained in:
2025-05-21 19:39:09 -04:00
parent 7d2b71fe95
commit ec1713c95f
27 changed files with 5843 additions and 0 deletions

View File

@@ -0,0 +1,320 @@
using Microsoft.EntityFrameworkCore;
namespace MangaReader.Core.Data;
public class Manga
{
public int MangaId { get; set; }
public required string Slug { get; set; }
public required string Title { get; set; }
public string? Description { get; set; }
public virtual ICollection<MangaCover> Covers { get; set; }
public virtual ICollection<MangaTitle> Titles { get; set; }
public virtual ICollection<MangaSource> Sources { get; set; }
public virtual ICollection<MangaGenre> Genres { get; set; }
public virtual ICollection<MangaChapter> Chapters { get; set; }
public Manga()
{
Covers = new HashSet<MangaCover>();
Titles = new HashSet<MangaTitle>();
Sources = new HashSet<MangaSource>();
Genres = new HashSet<MangaGenre>();
Chapters = new HashSet<MangaChapter>();
}
}
public class MangaCover
{
public int MangaCoverId { get; set; }
public int MangaId { get; set; }
public required Manga Manga { get; set; }
public required Guid Guid { get; set; }
public required string FileExtension { get; set; }
public string? Description { get; set; }
public bool IsPrimary { get; set; }
}
public class MangaTitle
{
public int MangaTitleId { get; set; }
public int MangaId { get; set; }
public required Manga Manga { get; set; }
public required string TitleEntry { get; set; }
public TitleType TitleType { get; set; }
}
public enum TitleType
{
Primary,
OfficialTranslation,
FanTranslation,
Synonym,
Abbreviation,
Romaji,
Japanese
}
public class Source
{
public int SourceId { get; set; }
public required string Name { get; set; }
}
public class MangaSource
{
public int MangaId { get; set; }
public required Manga Manga { get; set; }
public int SourceId { get; set; }
public required Source Source { get; set; }
public required string Url { get; set; }
}
public class Genre
{
public int GenreId { get; set; }
public required string Name { get; set; }
}
public class MangaGenre
{
public int MangaId { get; set; }
public required Manga Manga { get; set; }
public int GenreId { get; set; }
public required Genre Genre { get; set; }
}
public class MangaChapter
{
public int MangaChapterId { get; set; }
public int MangaId { get; set; }
public required Manga Manga { get; set; }
public int? VolumeNumber { get; set; }
public int ChapterNumber { get; set; }
public string? Title { get; set; }
public virtual ICollection<ChapterSource> Sources { get; set; } = [];
public virtual ICollection<ChapterPage> Pages { get; set; } = [];
}
public class ChapterSource
{
public int MangaChapterId { get; set; }
public required MangaChapter Chapter { get; set; }
public int SourceId { get; set; }
public required Source Source { get; set; }
public required string Url { get; set; }
}
public class ChapterPage
{
public int ChapterPageId { get; set; }
public int MangaChapterId { get; set; }
public required MangaChapter MangaChapter { get; set; }
public int PageNumber { get; set; }
}
public class MangaContext(DbContextOptions options) : DbContext(options)
{
public DbSet<Manga> Mangas { get; set; }
public DbSet<MangaCover> MangaCovers { get; set; }
public DbSet<MangaTitle> MangaTitles { get; set; }
public DbSet<Source> Sources { get; set; }
public DbSet<MangaSource> MangaSources { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<MangaGenre> MangaGenres { get; set; }
public DbSet<MangaChapter> MangaChapters { get; set; }
public DbSet<ChapterSource> ChapterSources { get; set; }
public DbSet<ChapterPage> ChapterPages { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
ConfigureManga(modelBuilder);
ConfigureMangaCover(modelBuilder);
ConfigureMangaTitle(modelBuilder);
ConfigureSource(modelBuilder);
ConfigureMangaSource(modelBuilder);
ConfigureGenre(modelBuilder);
ConfigureMangaGenre(modelBuilder);
ConfigureMangaChapter(modelBuilder);
ConfigureChapterSource(modelBuilder);
ConfigureChapterPage(modelBuilder);
}
private static void ConfigureManga(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Manga>()
.HasKey(x => x.MangaId);
modelBuilder.Entity<Manga>()
.HasIndex(x => x.Slug)
.IsUnique();
}
private static void ConfigureMangaCover(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MangaCover>()
.HasKey(x => x.MangaCoverId);
modelBuilder
.Entity<MangaCover>()
.HasOne(x => x.Manga)
.WithMany(x => x.Covers)
.HasForeignKey(x => x.MangaId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<MangaCover>()
.HasIndex(x => x.Guid)
.IsUnique();
//modelBuilder
// .Entity<MangaCover>()
// .HasIndex(x => new { x.MangaId, x.IsPrimary })
// .IsUnique()
// .HasFilter("[IsPrimary] = 1"); // Enforce only one primary cover per manga
}
private static void ConfigureMangaTitle(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MangaTitle>()
.HasKey(mangaTitle => mangaTitle.MangaTitleId);
modelBuilder.Entity<MangaTitle>()
.HasIndex(mangaTitle => new { mangaTitle.MangaId, mangaTitle.TitleEntry })
.IsUnique();
modelBuilder
.Entity<MangaTitle>()
.HasIndex(mangaTitle => mangaTitle.TitleEntry);
modelBuilder
.Entity<MangaTitle>()
.HasOne(x => x.Manga)
.WithMany(x => x.Titles)
.HasForeignKey(x => x.MangaId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigureSource(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Source>()
.HasKey(x => x.SourceId);
modelBuilder
.Entity<Source>()
.HasIndex(x => x.Name)
.IsUnique(true);
}
private static void ConfigureMangaSource(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MangaSource>()
.HasKey(mangaSource => new { mangaSource.MangaId, mangaSource.SourceId });
modelBuilder.Entity<MangaSource>()
.HasIndex(x => x.Url)
.IsUnique();
modelBuilder
.Entity<MangaSource>()
.HasOne(x => x.Manga)
.WithMany(x => x.Sources)
.HasForeignKey(x => x.MangaId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigureGenre(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Genre>()
.HasKey(x => x.GenreId);
modelBuilder
.Entity<Genre>()
.HasIndex(x => x.Name)
.IsUnique(true);
}
private static void ConfigureMangaGenre(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MangaGenre>()
.HasKey(mangaGenre => new { mangaGenre.MangaId, mangaGenre.GenreId });
modelBuilder
.Entity<MangaGenre>()
.HasOne(x => x.Manga)
.WithMany(x => x.Genres)
.HasForeignKey(x => x.MangaId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigureMangaChapter(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<MangaChapter>()
.HasKey(x => x.MangaChapterId);
modelBuilder
.Entity<MangaChapter>()
.HasOne(x => x.Manga)
.WithMany(x => x.Chapters)
.HasForeignKey(x => x.MangaId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigureChapterSource(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<ChapterSource>()
.HasKey(chapterSource => new { chapterSource.MangaChapterId, chapterSource.SourceId });
modelBuilder
.Entity<ChapterSource>()
.HasOne(x => x.Chapter)
.WithMany(x => x.Sources)
.HasForeignKey(x => x.MangaChapterId)
.OnDelete(DeleteBehavior.Cascade);
}
private static void ConfigureChapterPage(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<ChapterPage>()
.HasKey(chapterPage => chapterPage.ChapterPageId);
modelBuilder
.Entity<ChapterPage>()
.HasIndex(chapterPage => new { chapterPage.MangaChapterId, chapterPage.PageNumber })
.IsUnique(true);
modelBuilder
.Entity<ChapterPage>()
.HasOne(x => x.MangaChapter)
.WithMany(x => x.Pages)
.HasForeignKey(x => x.MangaChapterId)
.OnDelete(DeleteBehavior.Cascade);
}
}