using FileShare_EFCore.Models; using Microsoft.EntityFrameworkCore; namespace FileShare_EFCore.Database { /// /// 应用数据库上下文 —— 继承自 FileShare-EFCore 的 AppDbContext。 /// 所有业务实体在此注册 DbSet。 /// 这是 FileShare-API 和 FileShare-PC 共用的具体数据上下文。 /// public class AppDataContext(DatabaseConfiguration dbConfig) : AppDbContext(dbConfig) { /// 天气预报数据 public DbSet WeatherForecasts => Set(); /// 用户数据 public DbSet Users => Set(); /// API refresh token 数据 public DbSet ApiRefreshTokens => Set(); /// 文件库根目录数据 public DbSet ManagedLibraryRoots => Set(); /// 文件库文件记录数据 public DbSet ManagedFileRecords => Set(); /// 文件缩略图映射数据 public DbSet ManagedThumbnailMaps => Set(); /// /// 配置实体映射,包括主键、索引和属性约束。 /// /// 模型构建器。 protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-weather-forecast"); entity.Property(e => e.Summary).HasMaxLength(200); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-user"); entity.Property(e => e.Email).HasMaxLength(200); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-api-refresh-token"); entity.HasIndex(e => e.TokenHash).IsUnique().HasDatabaseName("idx-api-refresh-token-hash"); entity.HasIndex(e => e.UserId).HasDatabaseName("idx-api-refresh-token-user-id"); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-managed-library-root"); entity.HasIndex(e => e.Path).IsUnique().HasDatabaseName("idx-managed-library-root-path"); entity.Property(e => e.Path).HasMaxLength(1024); entity.Property(e => e.DisplayName).HasMaxLength(200); entity.Property(e => e.LastScanError).HasMaxLength(2000); entity.Property(e => e.IsAvailable).HasDefaultValue(true); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-managed-file-record"); entity.HasIndex(e => e.LibraryRootId).HasDatabaseName("idx-managed-file-record-root-id"); entity.HasIndex(e => e.ThumbnailId).HasDatabaseName("idx-managed-file-record-thumbnail-id"); entity.HasIndex(e => e.AbsolutePath).IsUnique().HasDatabaseName("idx-managed-file-record-absolute-path"); entity.HasIndex(e => new { e.MediaType, e.Exists }).HasDatabaseName("idx-managed-file-record-media-type-exists"); entity.HasIndex(e => e.LastPlayedAt).HasDatabaseName("idx-managed-file-record-last-played-at"); entity.Property(e => e.FileName).HasMaxLength(260); entity.Property(e => e.RelativePath).HasMaxLength(1024); entity.Property(e => e.AbsolutePath).HasMaxLength(2048); entity.Property(e => e.Extension).HasMaxLength(32); entity.Property(e => e.MediaType).HasMaxLength(20); entity.Property(e => e.ContentType).HasMaxLength(100); entity.HasOne(e => e.LibraryRoot) .WithMany(e => e.Files) .HasForeignKey(e => e.LibraryRootId) .OnDelete(DeleteBehavior.Cascade); entity.HasOne(e => e.Thumbnail) .WithMany(e => e.Files) .HasForeignKey(e => e.ThumbnailId) .OnDelete(DeleteBehavior.SetNull); }); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("pk-managed-thumbnail-map"); entity.HasIndex(e => e.LibraryRootId).HasDatabaseName("idx-managed-thumbnail-map-root-id"); entity.HasIndex(e => e.RelativePath).IsUnique().HasDatabaseName("idx-managed-thumbnail-map-relative-path"); entity.Property(e => e.RelativePath).HasMaxLength(1024); entity.Property(e => e.ContentType).HasMaxLength(100); entity.HasOne(e => e.LibraryRoot) .WithMany(e => e.Thumbnails) .HasForeignKey(e => e.LibraryRootId) .OnDelete(DeleteBehavior.Cascade); }); } } }