| File: Model.cs | Web Access |
| Project: src\playground\TestShop\CatalogModel\CatalogModel.csproj (CatalogModel) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace CatalogModel; public record Catalog(int FirstId, int NextId, bool IsLastPage, IEnumerable<CatalogItem> Data); public class CatalogDbContext(DbContextOptions<CatalogDbContext> options) : DbContext(options) { // https://learn.microsoft.com/ef/core/performance/advanced-performance-topics#compiled-queries private static readonly Func<CatalogDbContext, int?, int?, int?, int, IAsyncEnumerable<CatalogItem>> s_getCatalogItemsQuery = EF.CompileAsyncQuery((CatalogDbContext context, int? catalogBrandId, int? before, int? after, int pageSize) => context.CatalogItems.AsNoTracking() .OrderBy(ci => ci.Id) .Where(ci => catalogBrandId == null || ci.CatalogBrandId == catalogBrandId) .Where(ci => before == null || ci.Id <= before) .Where(ci => after == null || ci.Id >= after) .Take(pageSize + 1)); public Task<List<CatalogItem>> GetCatalogItemsCompiledAsync(int? catalogBrandId, int? before, int? after, int pageSize) { return ToListAsync(s_getCatalogItemsQuery(this, catalogBrandId, before, after, pageSize)); } public DbSet<CatalogItem> CatalogItems => Set<CatalogItem>(); public DbSet<CatalogBrand> CatalogBrands => Set<CatalogBrand>(); public DbSet<CatalogType> CatalogTypes => Set<CatalogType>(); protected override void OnModelCreating(ModelBuilder builder) { DefineCatalogBrand(builder.Entity<CatalogBrand>()); DefineCatalogItem(builder.Entity<CatalogItem>()); DefineCatalogType(builder.Entity<CatalogType>()); } private static void DefineCatalogType(EntityTypeBuilder<CatalogType> builder) { builder.ToTable("CatalogType"); builder.HasKey(ci => ci.Id); builder.Property(ci => ci.Id) .UseHiLo("catalog_type_hilo") .IsRequired(); builder.Property(cb => cb.Type) .IsRequired() .HasMaxLength(100); } private static void DefineCatalogItem(EntityTypeBuilder<CatalogItem> builder) { builder.ToTable("Catalog"); builder.Property(ci => ci.Id) .UseHiLo("catalog_hilo") .IsRequired(); builder.Property(ci => ci.Name) .IsRequired(true) .HasMaxLength(50); builder.Property(ci => ci.Price) .IsRequired(true); builder.Property(ci => ci.PictureFileName) .IsRequired(false); builder.Ignore(ci => ci.PictureUri); builder.HasOne(ci => ci.CatalogBrand) .WithMany() .HasForeignKey(ci => ci.CatalogBrandId); builder.HasOne(ci => ci.CatalogType) .WithMany() .HasForeignKey(ci => ci.CatalogTypeId); } private static void DefineCatalogBrand(EntityTypeBuilder<CatalogBrand> builder) { builder.ToTable("CatalogBrand"); builder.HasKey(ci => ci.Id); builder.Property(ci => ci.Id) .UseHiLo("catalog_brand_hilo") .IsRequired(); builder.Property(cb => cb.Brand) .IsRequired() .HasMaxLength(100); } private static async Task<List<T>> ToListAsync<T>(IAsyncEnumerable<T> asyncEnumerable) { var results = new List<T>(); await foreach (var value in asyncEnumerable) { results.Add(value); } return results; } } public class CatalogType { public int Id { get; set; } public required string Type { get; set; } } public class CatalogBrand { public int Id { get; set; } public required string Brand { get; set; } } public class CatalogItem { public int Id { get; set; } public required string Name { get; set; } public string? Description { get; set; } public decimal Price { get; set; } public required string PictureFileName { get; set; } public string? PictureUri { get; set; } public int CatalogTypeId { get; set; } public required CatalogType CatalogType { get; set; } public int CatalogBrandId { get; set; } public required CatalogBrand CatalogBrand { get; set; } public int AvailableStock { get; set; } public int RestockThreshold { get; set; } public int MaxStockThreshold { get; set; } public bool OnReorder { get; set; } }