using FinlyticCore.Database; using FinlyticCore.Entities.Settings; using FinlyticNews.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; namespace FinlyticNews.Database; /// /// Entity Framework Core database context for the news microservice, /// managing article sources, processed news, and matched assets. /// public class NewsDbContext : DbContext, ISettingsDbContext { /// /// Initializes a new instance of the class. /// /// The context configuration options. public NewsDbContext(DbContextOptions options) : base(options) { } /// /// Gets or sets the database set for dynamic settings. /// public DbSet DynamicSettings => Set(); /// /// Gets or sets the database set for configured article sources. /// public DbSet ArticleSources => Set(); /// /// Gets or sets the database set for news articles. /// public DbSet NewsArticles => Set(); /// /// Gets or sets the database set for matched assets. /// public DbSet MatchedAssets => Set(); /// /// Gets or sets the database set for blocked news URLs (unindexable or duplicate articles). /// public DbSet BlockedNewsUrls => Set(); /// /// Configures the model mapping, database constraints, and unique indices. /// /// The builder being used to construct the database schema model. protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.HasIndex(e => e.Key).IsUnique(); }); // Configure unique index on SourceUrl for deduplication check (idempotency) modelBuilder.Entity() .HasIndex(a => a.SourceUrl) .IsUnique(); // Performance & deduplication indexes for news queries modelBuilder.Entity() .HasIndex(a => new { a.PublishedAt, a.ScrapedAt }); modelBuilder.Entity() .HasIndex(a => a.Status); modelBuilder.Entity() .HasIndex(a => a.TitleHash); modelBuilder.Entity() .HasIndex(a => a.SimHash); modelBuilder.Entity() .HasIndex(m => m.Isin); // Blocked URLs index modelBuilder.Entity() .HasIndex(b => b.Url) .IsUnique(); // Configure relationship between NewsArticle and MatchedAssets modelBuilder.Entity() .HasOne(m => m.NewsArticle) .WithMany(a => a.MatchedAssets) .HasForeignKey(m => m.NewsArticleId) .OnDelete(DeleteBehavior.Cascade); } } public class NewsDbContextFactory : IDesignTimeDbContextFactory { public NewsDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseNpgsql("Host=localhost;Database=news;Username=postgres;Password=postgres"); return new NewsDbContext(optionsBuilder.Options); } }