Files
Data-Coupler/DataConnection/EF/ExistingDatabaseContext.cs
T

125 lines
4.8 KiB
C#

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Reflection;
using DataConnection.Enums;
namespace DataConnection.EF;
/// <summary>
/// DbContext per gestione database esistenti
/// </summary>
public class ExistingDatabaseContext : DbContext
{
private readonly Action<ModelBuilder> _modelConfigurator;
private readonly bool _enableAutoDiscovery;
private readonly Assembly _entityAssembly;
private readonly string _entityNamespace;
private readonly NamingStrategy _namingStrategy;
public ExistingDatabaseContext(
DbContextOptions options,
Action<ModelBuilder> 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<T>()
var genericMethod = entityMethod.MakeGenericMethod(entityType);
genericMethod.Invoke(modelBuilder, null);
}
}
}