using System; using System.Linq; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Reflection; using DataConnection.Enums; namespace DataConnection.EF; /// /// DbContext per gestione database esistenti /// public class ExistingDatabaseContext : DbContext { private readonly Action _modelConfigurator; private readonly bool _enableAutoDiscovery; private readonly Assembly _entityAssembly; private readonly string _entityNamespace; private readonly NamingStrategy _namingStrategy; public ExistingDatabaseContext( DbContextOptions options, Action modelConfigurator = null, bool enableAutoDiscovery = false, Assembly entityAssembly = null, string entityNamespace = null, NamingStrategy namingStrategy = NamingStrategy.Default) : base(options) { _modelConfigurator = modelConfigurator; _enableAutoDiscovery = enableAutoDiscovery; _entityAssembly = entityAssembly; _entityNamespace = entityNamespace; _namingStrategy = namingStrategy; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // Applica la strategia di mappatura dei nomi ApplyNamingStrategy(modelBuilder); // Applica la configurazione personalizzata se fornita _modelConfigurator?.Invoke(modelBuilder); // Scoperta automatica delle entità if (_enableAutoDiscovery && _entityAssembly != null) { DiscoverEntities(modelBuilder); } } private void ApplyNamingStrategy(ModelBuilder modelBuilder) { switch (_namingStrategy) { case NamingStrategy.CamelCase: foreach (var entity in modelBuilder.Model.GetEntityTypes()) { // Converti il nome della tabella in camelCase string tableName = entity.GetTableName(); if (!string.IsNullOrEmpty(tableName) && char.IsUpper(tableName[0])) entity.SetTableName(char.ToLower(tableName[0]) + tableName.Substring(1)); // Converti i nomi delle proprietà in camelCase foreach (var property in entity.GetProperties()) { string propertyName = property.GetColumnName(); if (!string.IsNullOrEmpty(propertyName) && char.IsUpper(propertyName[0])) property.SetColumnName(char.ToLower(propertyName[0]) + propertyName.Substring(1)); } } break; case NamingStrategy.SnakeCase: foreach (var entity in modelBuilder.Model.GetEntityTypes()) { // Converti il nome della tabella in snake_case string tableName = entity.GetTableName(); if (!string.IsNullOrEmpty(tableName)) entity.SetTableName(ConvertToSnakeCase(tableName)); // Converti i nomi delle proprietà in snake_case foreach (var property in entity.GetProperties()) { string propertyName = property.GetColumnName(); if (!string.IsNullOrEmpty(propertyName)) property.SetColumnName(ConvertToSnakeCase(propertyName)); } } break; } } private string ConvertToSnakeCase(string input) { if (string.IsNullOrEmpty(input)) return input; return string.Concat(input.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower(); } private void DiscoverEntities(ModelBuilder modelBuilder) { // Trova tutte le classi nel namespace specificato che potrebbero essere entità var entityTypes = _entityAssembly.GetTypes() .Where(t => !string.IsNullOrEmpty(_entityNamespace) ? t.Namespace == _entityNamespace : true) .Where(t => t.IsClass && !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null) .ToList(); // Metodo generico per aggiungere entità al modello var entityMethod = typeof(ModelBuilder).GetMethod("Entity", new Type[0]); foreach (var entityType in entityTypes) { // Usa reflection per chiamare il metodo generico Entity() var genericMethod = entityMethod.MakeGenericMethod(entityType); genericMethod.Invoke(modelBuilder, null); } } }