feat: Implement ExistingDatabaseContext for managing existing databases with customizable naming strategies and auto-discovery of entities

feat: Add SqlServerSchemaProvider for extracting database schema information from SQL Server

feat: Introduce DatabaseType and NamingStrategy enums for better database management and naming conventions

feat: Create IDatabaseDiscovery and IDatabaseManager interfaces for database operations and metadata retrieval

feat: Develop REST service client architecture with BaseRestServiceClient and SAP Business One specific implementation

feat: Implement REST service discovery page with UI for connecting to SAP Business One Service Layer and displaying discovered entities
This commit is contained in:
2025-04-29 00:16:03 +02:00
parent d1103c4e7d
commit 7346db3b63
22 changed files with 758 additions and 1 deletions
@@ -0,0 +1,124 @@
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);
}
}
}