using EgwCoreLib.Lux.Data.DbModel.Admin; namespace EgwCoreLib.Lux.Data { public partial class DataLayerContext : DbContext { private static Logger Log = LogManager.GetCurrentClassLogger(); private IConfiguration _configuration; public DataLayerContext() { } #if false public DataLayerContext(IConfiguration configuration) { _configuration = configuration; } #endif public DataLayerContext(DbContextOptions options) : base(options) { try { // se non ci fosse... crea o migra! Database.Migrate(); } catch (Exception exc) { Log.Error(exc, "Exception during context initialization 02"); } } public virtual DbSet DbSetCounters { get; set; } public virtual DbSet DbSetConfGlass { get; set; } public virtual DbSet DbSetConfProfile { get; set; } public virtual DbSet DbSetConfWood { get; set; } public virtual DbSet DbSetEnvirPar { get; set; } public virtual DbSet DbSetItemGroup { get; set; } public virtual DbSet DbSetItem { get; set; } public virtual DbSet DbSetSellItem { get; set; } public virtual DbSet DbSetTags { get; set; } public virtual DbSet DbSetCustomer { get; set; } public virtual DbSet DbSetDealer { get; set; } public virtual DbSet DbSetSupplier { get; set; } public virtual DbSet DbSetSupplierQualify { get; set; } public virtual DbSet DbSetBuyOrder { get; set; } public virtual DbSet DbSetBuyOrderRow { get; set; } public virtual DbSet DbSetMaterialReq { get; set; } public virtual DbSet DbSetBuyOrdRow2MatReq { get; set; } public virtual DbSet DbSetOffer { get; set; } public virtual DbSet DbSetOfferRow { get; set; } public virtual DbSet DbSetOrder { get; set; } public virtual DbSet DbSetOrderRow { get; set; } public virtual DbSet DbSetResource { get; set; } public virtual DbSet DbSetPhase { get; set; } public virtual DbSet DbSetCostDriver { get; set; } public virtual DbSet DbSetJobTask { get; set; } public virtual DbSet DbSetJobStep { get; set; } public virtual DbSet DbSetJobStepItem { get; set; } public virtual DbSet DbSetProdItem { get; set; } public virtual DbSet DbSetStockStatus { get; set; } public virtual DbSet DbSetMovType { get; set; } public virtual DbSet DbSetStockMov { get; set; } public virtual DbSet DbSetGenClass { get; set; } public virtual DbSet DbSetGenVal { get; set; } public virtual DbSet DbSetStatsDet { get; set; } public virtual DbSet DbSetStatsAggr { get; set; } public virtual DbSet DbSetProdGroup { get; set; } public virtual DbSet DbSetProdPlant { get; set; } public virtual DbSet DbSetProdBatch { get; set; } public virtual DbSet DbSetProdODL { get; set; } public virtual DbSet DbSetProdItem2ODL { get; set; } public virtual DbSet DbSetTemplate { get; set; } public virtual DbSet DbSetTemplateRow { get; set; } public virtual DbSet DbSetLingua { get; set; } public virtual DbSet DbSetVocabolario { get; set; } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { // default string connString = DbConfig.CONNECTION_STRING; if (string.IsNullOrEmpty(connString)) { #if DEBUG connString = "Server=mdb.ufficio;port=3306;database=Lux_000;uid=lux_user;pwd=Egal_pwd!;sslmode=None;"; //connString = "Server=mdb.ufficio;port=3306;database=Lux_000_dev;uid=lux_user;pwd=Egal_pwd!;sslmode=None;"; #else connString = "Server=mdb.ufficio;port=3306;database=Lux_000;uid=lux_user;pwd=Egal_pwd!;sslmode=None;"; #endif } if (!optionsBuilder.IsConfigured) { var serverVersion = ServerVersion.AutoDetect(connString); // 2026.01.09 aggiornata init componente POMELO #if false optionsBuilder.UseMySql(connString, serverVersion); #endif optionsBuilder.UseMySql(connString, serverVersion, options => { // Questo abilita il supporto JSON specifico per MySQL options.EnableStringComparisonTranslations(); }); // verificare setup componente #if false optionsBuilder .UseMySql(connString, serverVersion) .UseSnakeCaseNamingConvention(); // via EFCore.NamingConventions #endif } } protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys())) { relationship.DeleteBehavior = DeleteBehavior.Restrict; } // fix key multiple modelBuilder.Entity() .HasKey(jtt => new { jtt.JobID, jtt.CodTag }); modelBuilder.Entity() .HasKey(jst => new { jst.JobStepID, jst.CodTag }); // area Buy modelBuilder.Entity() .HasKey(sq => new { sq.SupplierID, sq.CodGroup }); modelBuilder.Entity() .HasKey(bm => new { bm.BuyOrderRowID, bm.MatReqID }); modelBuilder.Entity() .HasKey(x => new { x.ProdItemID, x.ProdODLID }); modelBuilder.Entity() .HasOne(x => x.ProductionItemNav) .WithMany(i => i.Item2OdlNav) .HasForeignKey(x => x.ProdItemID) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasOne(x => x.ProductionODLNav) .WithMany(o => o.Item2OdlNav) .HasForeignKey(x => x.ProdODLID) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasKey(jst => new { jst.Lingua, jst.Lemma }); // gestione dati DTX calcolati nel DB #if false modelBuilder.Entity() .Property(p => p.ProdLabel) // Utilizziamo la sintassi SQL di MySQL per la generazione del valore // HEX(ProdItemID) trasforma l'ID in esadecimale, LPAD aggiunge gli zeri a sinistra .HasComputedColumnSql("CONCAT('PT', LPAD(HEX(ProdItemID), 8, '0'))", stored: true); #endif modelBuilder.Entity() .Property(p => p.ProdItemTag) .IsRequired(false); // Permette l'inserimento iniziale nullo/vuoto modelBuilder.Entity() .HasIndex(x => new { x.ProdItemTag }) .HasDatabaseName("idx_prod_item_tag") .IsUnique(); // gestione deserializzazione smart x oggetti con liste implicite #if false modelBuilder.Entity() .Property(e => e.TagList) .HasConversion( v => JsonConvert.SerializeObject(v), // Da List a String (per il DB) v => JsonConvert.DeserializeObject>(v) ?? new List(), // Da String a List (per C#) new ValueComparer>( // Fondamentale per il tracking delle modifiche! (c1, c2) => c1.SequenceEqual(c2), c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())), c => c.ToList())); #endif // FixMe ToDo da rivedere: valutare x altri casi!!!! non pare essere formulazione migliore ma la successiva #if false modelBuilder.Entity() .Property(e => e.TagList) .HasColumnType("json"); #endif // modalità non valida x Pomelo 8 e MariaDb #if false // gestione dei dati serializzati di stima tempi come JSON modelBuilder.Entity() .OwnsMany(x => x.WorkGroupList, b => { b.ToJson(); }); #endif #if false // JobTask ↔ Tags modelBuilder.Entity() .HasOne(j => j.JobTaskNav) .WithMany(t => t.TagNav) .HasForeignKey(j => j.JobID); modelBuilder.Entity() .HasOne(j => j.TagNav) .WithMany(t => t.JobTaskNav) .HasForeignKey(j => j.cod); // JobStep ↔ Tags modelBuilder.Entity() .HasMany(js => js.TagNav) .WithMany(t => t.JobSteps) .UsingEntity(j => j.ToTable("JobStepTags")); #endif // fix chiavi multiple modelBuilder.Entity() .HasKey(c => new { c.RefYear, c.CountName }); modelBuilder.Entity() .HasKey(c => new { c.GlassID }); modelBuilder.Entity() .HasKey(c => new { c.ProfileID }); modelBuilder.Entity() .HasKey(c => new { c.WoodID }); // fix valori timestamp modelBuilder.Entity(entity => { entity.Property(e => e.DtCreate) .HasColumnType("timestamp") .HasDefaultValueSql("CURRENT_TIMESTAMP") .ValueGeneratedOnAdd(); entity.Property(e => e.DtMod) .HasColumnType("timestamp") .HasDefaultValueSql("CURRENT_TIMESTAMP") .ValueGeneratedOnAddOrUpdate(); }); // indici tabelle stats modelBuilder.Entity() .HasIndex(x => new { x.Hour, x.Environment, x.Type }) .HasDatabaseName("idx_statsdet_hour_env_type") .IsUnique(); modelBuilder.Entity() .HasIndex(x => new { x.Hour }) .HasDatabaseName("idx_statsaggr_hour") .IsUnique(); // seed finale dei dati di default modelBuilder.Seed(); OnModelCreatingPartial(modelBuilder); } public void DbForceMigrate() { try { // se non ci fosse... crea o migra! Database.Migrate(); Log.Info("DbForceMigrate: done!"); } catch (Exception exc) { Log.Error(exc, "DbForceMigrate: Exception during context initialization 01"); } } } }