using BlueLaminate.EFCore.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace BlueLaminate.EFCore.Configurations; public class SkinLandListingConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder entity) { // skin.land's offer id is the natural key; ingest upserts against it and must // never create duplicates. entity.HasIndex(e => e.ListingId).IsUnique(); entity.Property(e => e.Price).HasPrecision(18, 2); // Full precision (matches SkinInstance/cs.money) even though skin.land offers // aren't fingerprinted — keep the float lossless for later analysis. entity.Property(e => e.FloatValue).HasColumnType("numeric(20,18)"); // Enum as text so the DB is self-describing (matches the project's leaning). entity.Property(e => e.Status).HasConversion(); // Targeted scrape: results are filtered/sorted by skin+wear and by activity. entity.HasIndex(e => new { e.SkinId, e.ConditionId }); entity.HasIndex(e => e.Status); // Each job targets a known skin, so this link is required (Restrict: a skin with // live listings shouldn't be deleted out from under them). entity.HasOne(e => e.Skin) .WithMany() .HasForeignKey(e => e.SkinId) .OnDelete(DeleteBehavior.Restrict); entity.HasOne(e => e.Condition) .WithMany() .HasForeignKey(e => e.ConditionId) .OnDelete(DeleteBehavior.SetNull); } }