275 lines
11 KiB
C#
275 lines
11 KiB
C#
using EgwCoreLib.Lux.Data.DbModel.Catalog;
|
|
using EgwCoreLib.Lux.Data.DbModel.Config;
|
|
using EgwCoreLib.Lux.Data.DbModel.Cost;
|
|
using EgwCoreLib.Lux.Data.DbModel.Items;
|
|
using EgwCoreLib.Lux.Data.DbModel.Production;
|
|
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
|
using EgwCoreLib.Lux.Data.DbModel.Stats;
|
|
using EgwCoreLib.Lux.Data.DbModel.Stock;
|
|
using EgwCoreLib.Lux.Data.DbModel.Task;
|
|
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using NLog;
|
|
|
|
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<DataLayerContext> 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<CounterModel> DbSetCounters { get; set; }
|
|
public virtual DbSet<GlassModel> DbSetConfGlass { get; set; }
|
|
public virtual DbSet<ProfileModel> DbSetConfProfile { get; set; }
|
|
public virtual DbSet<WoodModel> DbSetConfWood { get; set; }
|
|
public virtual DbSet<EnvirParamModel> DbSetEnvirPar { get; set; }
|
|
|
|
public virtual DbSet<ItemGroupModel> DbSetItemGroup { get; set; }
|
|
public virtual DbSet<ItemModel> DbSetItem { get; set; }
|
|
public virtual DbSet<SellingItemModel> DbSetSellItem { get; set; }
|
|
public virtual DbSet<TagsModel> DbSetTags { get; set; }
|
|
public virtual DbSet<CustomerModel> DbSetCustomer { get; set; }
|
|
public virtual DbSet<DealerModel> DbSetDealer { get; set; }
|
|
public virtual DbSet<SupplierModel> DbSetSupplier { get; set; }
|
|
public virtual DbSet<OfferModel> DbSetOffer { get; set; }
|
|
public virtual DbSet<OfferRowModel> DbSetOfferRow { get; set; }
|
|
public virtual DbSet<OrderModel> DbSetOrder { get; set; }
|
|
public virtual DbSet<OrderRowModel> DbSetOrderRow { get; set; }
|
|
public virtual DbSet<ResourceModel> DbSetResource { get; set; }
|
|
public virtual DbSet<PhaseModel> DbSetPhase { get; set; }
|
|
public virtual DbSet<CostDriverModel> DbSetCostDriver { get; set; }
|
|
public virtual DbSet<JobTaskModel> DbSetJobTask { get; set; }
|
|
public virtual DbSet<JobStepModel> DbSetJobStep { get; set; }
|
|
public virtual DbSet<JobStepItemModel> DbSetJobStepItem { get; set; }
|
|
public virtual DbSet<ProductionItemModel> DbSetProdItem { get; set; }
|
|
public virtual DbSet<StockStatusModel> DbSetStockStatus { get; set; }
|
|
public virtual DbSet<MovTypeModel> DbSetMovType { get; set; }
|
|
public virtual DbSet<StockMovModel> DbSetStockMov { get; set; }
|
|
public virtual DbSet<GenClassModel> DbSetGenClass { get; set; }
|
|
public virtual DbSet<GenValueModel> DbSetGenVal { get; set; }
|
|
public virtual DbSet<StatsDetailModel> DbSetStatsDet { get; set; }
|
|
public virtual DbSet<StatsAggregatedModel> DbSetStatsAggr { get; set; }
|
|
public virtual DbSet<ProductionGroupModel> DbSetProdGroup { get; set; }
|
|
public virtual DbSet<ProductionPlantModel> DbSetProdPlant { get; set; }
|
|
public virtual DbSet<ProductionBatchModel> DbSetProdBatch { get; set; }
|
|
|
|
public virtual DbSet<ProductionODLModel> DbSetProdODL { get; set; }
|
|
public virtual DbSet<ProductionItem2ODLModel> DbSetProdItem2ODL { get; set; }
|
|
|
|
public virtual DbSet<TemplateModel> DbSetTemplate { get; set; }
|
|
public virtual DbSet<TemplateRowModel> DbSetTemplateRow { 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<JobTaskTagModel>()
|
|
.HasKey(jtt => new { jtt.JobID, jtt.CodTag });
|
|
modelBuilder.Entity<JobStepTagModel>()
|
|
.HasKey(jst => new { jst.JobStepID, jst.CodTag });
|
|
|
|
modelBuilder.Entity<ProductionItem2ODLModel>()
|
|
.HasKey(x => new { x.ProdItemID, x.ProdODLID });
|
|
|
|
modelBuilder.Entity<ProductionItem2ODLModel>()
|
|
.HasOne(x => x.ProductionItemNav)
|
|
.WithMany(i => i.Item2OdlNav)
|
|
.HasForeignKey(x => x.ProdItemID)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
modelBuilder.Entity<ProductionItem2ODLModel>()
|
|
.HasOne(x => x.ProductionODLNav)
|
|
.WithMany(o => o.Item2OdlNav)
|
|
.HasForeignKey(x => x.ProdODLID)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
|
|
// gestione dati DTX calcolati nel DB
|
|
#if false
|
|
modelBuilder.Entity<ProductionItemModel>()
|
|
.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<ProductionItemModel>()
|
|
.Property(p => p.ProdItemTag)
|
|
.IsRequired(false); // Permette l'inserimento iniziale nullo/vuoto
|
|
modelBuilder.Entity<ProductionItemModel>()
|
|
.HasIndex(x => new { x.ProdItemTag })
|
|
.HasDatabaseName("idx_prod_item_tag")
|
|
.IsUnique();
|
|
|
|
// gestione deserializzazione smart x oggetti con liste implicite
|
|
#if false
|
|
modelBuilder.Entity<ProductionAssignModel>()
|
|
.Property(e => e.TagList)
|
|
.HasConversion(
|
|
v => JsonConvert.SerializeObject(v), // Da List a String (per il DB)
|
|
v => JsonConvert.DeserializeObject<List<string>>(v) ?? new List<string>(), // Da String a List (per C#)
|
|
new ValueComparer<List<string>>( // 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<ProductionAssignModel>()
|
|
.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<ProductionGroupModel>()
|
|
.OwnsMany(x => x.WorkGroupList, b =>
|
|
{
|
|
b.ToJson();
|
|
});
|
|
#endif
|
|
|
|
#if false
|
|
// JobTask ↔ Tags
|
|
modelBuilder.Entity<JobTaskTagModel>()
|
|
.HasOne(j => j.JobTaskNav)
|
|
.WithMany(t => t.TagNav)
|
|
.HasForeignKey(j => j.JobID);
|
|
modelBuilder.Entity<JobTaskTagModel>()
|
|
.HasOne(j => j.TagNav)
|
|
.WithMany(t => t.JobTaskNav)
|
|
.HasForeignKey(j => j.cod);
|
|
|
|
// JobStep ↔ Tags
|
|
modelBuilder.Entity<JobStepTagModel>()
|
|
.HasMany(js => js.TagNav)
|
|
.WithMany(t => t.JobSteps)
|
|
.UsingEntity(j => j.ToTable("JobStepTags"));
|
|
#endif
|
|
|
|
// fix chiavi multiple
|
|
modelBuilder.Entity<CounterModel>()
|
|
.HasKey(c => new { c.RefYear, c.CountName });
|
|
|
|
modelBuilder.Entity<GlassModel>()
|
|
.HasKey(c => new { c.GlassID });
|
|
modelBuilder.Entity<ProfileModel>()
|
|
.HasKey(c => new { c.ProfileID });
|
|
modelBuilder.Entity<WoodModel>()
|
|
.HasKey(c => new { c.WoodID });
|
|
|
|
// fix valori timestamp
|
|
modelBuilder.Entity<StockMovModel>(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<StatsDetailModel>()
|
|
.HasIndex(x => new { x.Hour, x.Environment, x.Type })
|
|
.HasDatabaseName("idx_statsdet_hour_env_type")
|
|
.IsUnique();
|
|
modelBuilder.Entity<StatsAggregatedModel>()
|
|
.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");
|
|
}
|
|
}
|
|
}
|
|
}
|