Add collector fields, including market value
Rating, notes, condition, region, purchase price and date, plus a market
value carrying the timestamp and source that make it interpretable.
Condition is load-bearing rather than cosmetic: price feeds quote per
condition, so it selects which quoted price applies to a copy. Market value
records when it was captured and where it came from — a collection total is
only as good as its staleness — and an edit to an unrelated field leaves
that timestamp alone, so a stale price cannot start looking freshly checked.
Two storage decisions worth naming:
* Money is stored as integer minor units. SQLite has no decimal type and
EF Core maps decimal to TEXT, which compares lexically: "9.00" sorts
above "10.00" and SUM is unavailable. A value converter keeps decimals
in C# while ordering and totalling work. A test pins the ordering.
* Enums serialise as names. The default is ordinals, which meant the API
rejected the browser's {"condition":"Cib"} with a 400 while the C# tests
passed, because they round-tripped ints and never spoke the client's
dialect. The tests now share the API's serializer options.
Also fixes a data-loss bug in the Python tools. Both built their PUT body
from a hardcoded list of field names, so any column added to the model was
omitted and therefore nulled. Adding collector fields meant the next art or
enrichment run would have erased every rating, note, condition, price and
valuation in the library. Payloads are now built by excluding the handful of
server-owned fields, so new columns carry through by default.
The migration was rehearsed against a copy of the live database before being
applied: 105 rows, descriptions and developers intact.
67 backend tests, 8 frontend.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using LudosData.Api.Domain;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace LudosData.Api.Data;
|
||||
|
||||
@@ -13,6 +14,15 @@ public class LudosDbContext(DbContextOptions<LudosDbContext> options)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
// SQLite has no decimal type. EF Core's default is to store decimal as
|
||||
// TEXT, which compares lexically — "9.00" sorts above "10.00", and SUM
|
||||
// is not available at all. Money is therefore stored as integer minor
|
||||
// units and converted on the way in and out, so ordering by value and
|
||||
// totalling a collection both behave.
|
||||
var moneyToCents = new ValueConverter<decimal?, long?>(
|
||||
value => value == null ? null : (long)Math.Round(value.Value * 100m, MidpointRounding.AwayFromZero),
|
||||
cents => cents == null ? null : cents.Value / 100m);
|
||||
|
||||
builder.Entity<Game>(game =>
|
||||
{
|
||||
game.HasOne(g => g.Owner)
|
||||
@@ -20,11 +30,19 @@ public class LudosDbContext(DbContextOptions<LudosDbContext> options)
|
||||
.HasForeignKey(g => g.OwnerId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
game.Property(g => g.PurchasePrice).HasConversion(moneyToCents);
|
||||
game.Property(g => g.MarketValue).HasConversion(moneyToCents);
|
||||
|
||||
// Stored as an enum's underlying int; readable names live in the API.
|
||||
game.Property(g => g.Condition).HasConversion<int>();
|
||||
game.Property(g => g.Region).HasConversion<int>();
|
||||
|
||||
// Every list query filters by owner first, then narrows or sorts on
|
||||
// these columns, so they lead the composite indexes.
|
||||
game.HasIndex(g => new { g.OwnerId, g.Title });
|
||||
game.HasIndex(g => new { g.OwnerId, g.System });
|
||||
game.HasIndex(g => new { g.OwnerId, g.Genre });
|
||||
game.HasIndex(g => new { g.OwnerId, g.Rating });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using LudosData.Api.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LudosData.Api.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(LudosDbContext))]
|
||||
[Migration("20260804171435_AddCollectorFields")]
|
||||
partial class AddCollectorFields
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "10.0.10");
|
||||
|
||||
modelBuilder.Entity("LudosData.Api.Domain.AppUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Art")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LudosData.Api.Domain.Game", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Art")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Condition")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Developer")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Dumped")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("Finished")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Genre")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("MarketValue")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("MarketValueSource")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("MarketValueUpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Own")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("OwnerId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Played")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Publisher")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateOnly?>("PurchaseDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("PurchasePrice")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Rating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Region")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("System")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Year")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId", "Genre");
|
||||
|
||||
b.HasIndex("OwnerId", "Rating");
|
||||
|
||||
b.HasIndex("OwnerId", "System");
|
||||
|
||||
b.HasIndex("OwnerId", "Title");
|
||||
|
||||
b.ToTable("Games");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LudosData.Api.Domain.Game", b =>
|
||||
{
|
||||
b.HasOne("LudosData.Api.Domain.AppUser", "Owner")
|
||||
.WithMany("Games")
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("LudosData.Api.Domain.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("LudosData.Api.Domain.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LudosData.Api.Domain.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("LudosData.Api.Domain.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LudosData.Api.Domain.AppUser", b =>
|
||||
{
|
||||
b.Navigation("Games");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LudosData.Api.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCollectorFields : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Condition",
|
||||
table: "Games",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "MarketValue",
|
||||
table: "Games",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "MarketValueSource",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
maxLength: 100,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "MarketValueUpdatedAt",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Notes",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<DateOnly>(
|
||||
name: "PurchaseDate",
|
||||
table: "Games",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "PurchasePrice",
|
||||
table: "Games",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Rating",
|
||||
table: "Games",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Region",
|
||||
table: "Games",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Games_OwnerId_Rating",
|
||||
table: "Games",
|
||||
columns: new[] { "OwnerId", "Rating" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Games_OwnerId_Rating",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Condition",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MarketValue",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MarketValueSource",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MarketValueUpdatedAt",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Notes",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PurchaseDate",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PurchasePrice",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Rating",
|
||||
table: "Games");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Region",
|
||||
table: "Games");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,9 @@ namespace LudosData.Api.Data.Migrations
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Condition")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
@@ -123,6 +126,19 @@ namespace LudosData.Api.Data.Migrations
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("MarketValue")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("MarketValueSource")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTimeOffset?>("MarketValueUpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Notes")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Own")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -137,6 +153,18 @@ namespace LudosData.Api.Data.Migrations
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateOnly?>("PurchaseDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<long?>("PurchasePrice")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Rating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Region")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("System")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("TEXT");
|
||||
@@ -157,6 +185,8 @@ namespace LudosData.Api.Data.Migrations
|
||||
|
||||
b.HasIndex("OwnerId", "Genre");
|
||||
|
||||
b.HasIndex("OwnerId", "Rating");
|
||||
|
||||
b.HasIndex("OwnerId", "System");
|
||||
|
||||
b.HasIndex("OwnerId", "Title");
|
||||
|
||||
Reference in New Issue
Block a user