Files

118 lines
4.9 KiB
C#

using Microsoft.EntityFrameworkCore;
using YAPContracts.Enums;
using YAPContracts.Infrastructure;
using YAPDatabase.Models;
namespace YAPDatabase
{
internal class YAPDbContext(IConfigurationDatabase configuration) : DbContext
{
private readonly IConfigurationDatabase _configuration = configuration;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(_configuration?.ConnectionString, o => o.SetPostgresVersion(12, 2));
base.OnConfiguring(optionsBuilder);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// one Table-per-Hierarchy (TPH) for Users
modelBuilder.Entity<User>()
.HasDiscriminator<UserType>("Role")
.HasValue<Worker>(UserType.Worker)
.HasValue<Storekeeper>(UserType.Storekeeper);
modelBuilder.Entity<User>()
.HasKey(u => u.Id);
modelBuilder.Entity<User>()
.Property(u => u.Login).IsRequired();
modelBuilder.Entity<User>()
.Property(u => u.Email).IsRequired();
modelBuilder.Entity<User>()
.Property(u => u.PasswordHash).IsRequired();
// intermediate tables for many-to-many relationships
modelBuilder.Entity<ComponentInProduct>()
.HasKey(x => new { x.ComponentId, x.ProductId });
modelBuilder.Entity<ComponentInProductSet>()
.HasKey(x => new { x.ComponentId, x.ProductSetId });
modelBuilder.Entity<ProductInPurchase>()
.HasKey(x => new { x.ProductId, x.PurchaseId });
modelBuilder.Entity<ProductSetInPurchase>()
.HasKey(x => new { x.ProductSetId, x.PurchaseId });
// onlyActual & isDeleted properties for soft delete
modelBuilder.Entity<ProductSet>()
.Property(ps => ps.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<ProductSet>()
.HasIndex(e => new { e.SetName, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted sets
modelBuilder.Entity<Product>()
.Property(p => p.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<Product>()
.HasIndex(e => new { e.Name, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted products
modelBuilder.Entity<Component>()
.Property(c => c.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<Component>()
.HasIndex(e => new { e.Name, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted components
// User relationships
// Worker can create Purchases and Comments here
modelBuilder.Entity<Purchase>()
.HasOne<Worker>(c => c.User) // only Worker can create Purchase
.WithMany(w => w.Purchases)
.HasForeignKey(p => p.UserId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Comment>()
.HasOne<Worker>(c => c.User)
.WithMany(w => w.Comments)
.HasForeignKey(c => c.UserId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Comment>().HasOne<ProductSet>(c => c.ProductSet)
.WithMany(ps => ps.Comments)
.HasForeignKey(c => c.ProductSetId)
.OnDelete(DeleteBehavior.Cascade); // deleting a ProductSet will delete its Comments
// Storekeeper can manage Components and ProductOrders here
modelBuilder.Entity<ProductOrder>()
.HasOne<Storekeeper>(c => c.Storekeeper) // only Storekeeper can create ProductOrder
.WithMany(w => w.ProductOrders)
.HasForeignKey(p => p.UserId)
.OnDelete(DeleteBehavior.Cascade);
}
public DbSet<User> Users { get; set; } // single table
public DbSet<Comment> Comments { get; set; }
public DbSet<Component> Components { get; set; }
public DbSet<ComponentInProduct> ComponentsInProduct { get; set; }
public DbSet<ComponentInProductSet> ComponentsInProductSet { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<ProductInPurchase> ProductsInPurchase { get; set; }
public DbSet<ProductOrder> ProductOrders { get; set; }
public DbSet<ProductSet> ProductSets { get; set; }
public DbSet<ProductSetInPurchase> ProductSetsInPurchase { get; set; }
public DbSet<Purchase> Purchases { get; set; }
}
}