Implementato il supporto per la scoperta e la visualizzazione dello schema del database, inclusa la creazione di provider specifici per SQL Server e l'integrazione con il servizio di connessione al database.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using DataConnection.EF.SchemaProviders;
|
||||
using DataConnection.Enums;
|
||||
using DataConnection.Interfaces;
|
||||
|
||||
namespace DataConnection.EF;
|
||||
|
||||
/// <summary>
|
||||
/// Factory per la creazione di provider di schema del database
|
||||
/// </summary>
|
||||
public class DatabaseSchemaProviderFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Crea un provider di schema in base al tipo di database
|
||||
/// </summary>
|
||||
/// <param name="databaseType">Tipo di database</param>
|
||||
/// <returns>Provider di schema appropriato</returns>
|
||||
public static IDatabaseSchemaProvider CreateProvider(DatabaseType databaseType)
|
||||
{
|
||||
return databaseType switch
|
||||
{
|
||||
DatabaseType.SqlServer => new SqlServerSchemaProvider(),
|
||||
// Aggiungere qui altri provider quando implementati
|
||||
// DatabaseType.MySql => new MySqlSchemaProvider(),
|
||||
// DatabaseType.PostgreSql => new PostgreSqlSchemaProvider(),
|
||||
// DatabaseType.Oracle => new OracleSchemaProvider(),
|
||||
// DatabaseType.Sqlite => new SqliteSchemaProvider(),
|
||||
// DatabaseType.DB2 => new DB2SchemaProvider(),
|
||||
// DatabaseType.SapHana => new SapHanaSchemaProvider(),
|
||||
_ => throw new NotSupportedException($"Tipo di database non supportato per l'estrazione dello schema: {databaseType}")
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -61,12 +61,19 @@ public class DbManagerOptions
|
||||
/// </summary>
|
||||
public string DatabaseName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tipo di database (SqlServer, MySql, ecc.)
|
||||
/// </summary>
|
||||
public DatabaseType DatabaseType { get; set; } = DatabaseType.SqlServer;
|
||||
|
||||
/// <summary>
|
||||
/// Configura automaticamente il servizio di scoperta database in base al tipo di database
|
||||
/// </summary>
|
||||
/// <param name="databaseType">Tipo di database</param>
|
||||
public void ConfigureDatabaseDiscovery(DatabaseType databaseType)
|
||||
{
|
||||
DatabaseType = databaseType;
|
||||
|
||||
switch (databaseType)
|
||||
{
|
||||
case DatabaseType.SqlServer:
|
||||
|
||||
@@ -105,51 +105,23 @@ public class EFCoreDatabaseManager : IDatabaseManager
|
||||
}
|
||||
|
||||
public async Task<IDictionary<string, IEnumerable<DbColumnInfo>>> GetDatabaseSchemaAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Assicurarsi che il contesto sia connesso
|
||||
await _context.Database.OpenConnectionAsync();
|
||||
|
||||
var result = new Dictionary<string, IEnumerable<DbColumnInfo>>();
|
||||
// Usa la factory per ottenere il provider appropriato in base al tipo di database
|
||||
var schemaProvider = DatabaseSchemaProviderFactory.CreateProvider(_options.DatabaseType);
|
||||
|
||||
// Ottiene tutte le entità dal modello
|
||||
var model = _context.Model;
|
||||
var entityTypes = model.GetEntityTypes().ToList();
|
||||
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
var tableName = entityType.GetTableName();
|
||||
var schemaName = entityType.GetSchema();
|
||||
var fullTableName = string.IsNullOrEmpty(schemaName) ? tableName : $"{schemaName}.{tableName}";
|
||||
|
||||
var columns = new List<DbColumnInfo>();
|
||||
|
||||
foreach (var property in entityType.GetProperties())
|
||||
{
|
||||
var columnInfo = new DbColumnInfo
|
||||
{
|
||||
Name = property.GetColumnName(),
|
||||
DataType = property.GetColumnType(),
|
||||
IsNullable = property.IsNullable,
|
||||
IsPrimaryKey = property.IsPrimaryKey()
|
||||
};
|
||||
|
||||
// Verifica se è una foreign key
|
||||
var foreignKeys = entityType.GetForeignKeys().Where(fk => fk.Properties.Contains(property));
|
||||
if (foreignKeys.Any())
|
||||
{
|
||||
var fk = foreignKeys.First();
|
||||
columnInfo.IsForeignKey = true;
|
||||
columnInfo.ReferencedTable = fk.PrincipalEntityType.GetTableName();
|
||||
columnInfo.ReferencedColumn = fk.PrincipalKey.Properties.First().GetColumnName();
|
||||
// Usa il provider per ottenere lo schema
|
||||
return await schemaProvider.GetDatabaseSchemaAsync(_context.Database.GetConnectionString());
|
||||
}
|
||||
|
||||
columns.Add(columnInfo);
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Errore nel recupero dello schema del database: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
result.Add(fullTableName, columns);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Threading.Tasks;
|
||||
using DataConnection.Interfaces;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace DataConnection.EF.SchemaProviders;
|
||||
|
||||
/// <summary>
|
||||
/// Provider di schema per database SQL Server
|
||||
/// </summary>
|
||||
public class SqlServerSchemaProvider : IDatabaseSchemaProvider
|
||||
{
|
||||
public async Task<IDictionary<string, IEnumerable<DbColumnInfo>>> GetDatabaseSchemaAsync(string connectionString)
|
||||
{
|
||||
var result = new Dictionary<string, IEnumerable<DbColumnInfo>>();
|
||||
|
||||
try
|
||||
{
|
||||
using (var connection = new SqlConnection(connectionString))
|
||||
{
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Query per ottenere la struttura delle tabelle in SQL Server
|
||||
string sql = @"
|
||||
SELECT
|
||||
SCHEMA_NAME(t.schema_id) + '.' + t.name AS TableName,
|
||||
c.name AS ColumnName,
|
||||
tp.name AS DataType,
|
||||
c.max_length,
|
||||
c.precision,
|
||||
c.scale,
|
||||
c.is_nullable,
|
||||
CASE WHEN pk.column_id IS NOT NULL THEN 1 ELSE 0 END AS IsPrimaryKey,
|
||||
CASE WHEN fk.parent_column_id IS NOT NULL THEN 1 ELSE 0 END AS IsForeignKey,
|
||||
SCHEMA_NAME(ref_t.schema_id) + '.' + ref_t.name AS ReferencedTable,
|
||||
ref_c.name AS ReferencedColumn
|
||||
FROM
|
||||
sys.tables t
|
||||
INNER JOIN
|
||||
sys.columns c ON t.object_id = c.object_id
|
||||
INNER JOIN
|
||||
sys.types tp ON c.user_type_id = tp.user_type_id
|
||||
LEFT JOIN
|
||||
(SELECT
|
||||
ic.object_id,
|
||||
ic.column_id
|
||||
FROM
|
||||
sys.indexes i
|
||||
INNER JOIN
|
||||
sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
||||
WHERE
|
||||
i.is_primary_key = 1) pk ON t.object_id = pk.object_id AND c.column_id = pk.column_id
|
||||
LEFT JOIN
|
||||
sys.foreign_key_columns fk ON t.object_id = fk.parent_object_id AND c.column_id = fk.parent_column_id
|
||||
LEFT JOIN
|
||||
sys.tables ref_t ON fk.referenced_object_id = ref_t.object_id
|
||||
LEFT JOIN
|
||||
sys.columns ref_c ON fk.referenced_object_id = ref_c.object_id AND fk.referenced_column_id = ref_c.column_id
|
||||
WHERE
|
||||
t.is_ms_shipped = 0
|
||||
ORDER BY
|
||||
TableName, c.column_id";
|
||||
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
command.CommandType = CommandType.Text;
|
||||
|
||||
using (var reader = await command.ExecuteReaderAsync())
|
||||
{
|
||||
string currentTable = null;
|
||||
List<DbColumnInfo> columns = null;
|
||||
|
||||
while (await reader.ReadAsync())
|
||||
{
|
||||
string tableName = reader.GetString(0);
|
||||
|
||||
// Se stiamo passando a una nuova tabella, aggiungiamo la tabella precedente e creiamo una nuova lista
|
||||
if (currentTable != tableName)
|
||||
{
|
||||
if (currentTable != null && columns != null && columns.Count > 0)
|
||||
{
|
||||
result[currentTable] = columns;
|
||||
}
|
||||
|
||||
currentTable = tableName;
|
||||
columns = new List<DbColumnInfo>();
|
||||
}
|
||||
|
||||
// Formato del tipo di dati con precisione e scala per tipi numerici o lunghezza per tipi stringa
|
||||
string dataType = reader.GetString(2);
|
||||
int maxLength = reader.GetInt16(3);
|
||||
byte precision = reader.GetByte(4);
|
||||
byte scale = reader.GetByte(5);
|
||||
|
||||
// Formattazione tipo di dati per SQL Server
|
||||
string formattedDataType = FormatSqlServerDataType(dataType, maxLength, precision, scale);
|
||||
|
||||
var columnInfo = new DbColumnInfo
|
||||
{
|
||||
Name = reader.GetString(1),
|
||||
DataType = formattedDataType,
|
||||
IsNullable = reader.GetBoolean(6),
|
||||
IsPrimaryKey = reader.GetInt32(7) == 1,
|
||||
IsForeignKey = reader.GetInt32(8) == 1,
|
||||
ReferencedTable = reader.IsDBNull(9) ? null : reader.GetString(9),
|
||||
ReferencedColumn = reader.IsDBNull(10) ? null : reader.GetString(10)
|
||||
};
|
||||
|
||||
columns?.Add(columnInfo);
|
||||
}
|
||||
|
||||
// Aggiungiamo l'ultima tabella
|
||||
if (currentTable != null && columns != null && columns.Count > 0)
|
||||
{
|
||||
result[currentTable] = columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Errore nel recupero dello schema del database SQL Server: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string FormatSqlServerDataType(string dataType, int maxLength, byte precision, byte scale)
|
||||
{
|
||||
string formattedDataType = dataType;
|
||||
|
||||
if (dataType == "nvarchar" || dataType == "varchar" || dataType == "char" || dataType == "nchar")
|
||||
{
|
||||
if (maxLength == -1)
|
||||
formattedDataType += "(MAX)";
|
||||
else if (dataType.StartsWith("n")) // tipi Unicode - la lunghezza è in byte, dobbiamo dividerla per 2
|
||||
formattedDataType += $"({maxLength / 2})";
|
||||
else
|
||||
formattedDataType += $"({maxLength})";
|
||||
}
|
||||
else if (dataType == "decimal" || dataType == "numeric")
|
||||
{
|
||||
formattedDataType += $"({precision},{scale})";
|
||||
}
|
||||
|
||||
return formattedDataType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataConnection.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Interfaccia per provider di estrazione dello schema del database
|
||||
/// </summary>
|
||||
public interface IDatabaseSchemaProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Estrae lo schema del database (tabelle e colonne)
|
||||
/// </summary>
|
||||
/// <param name="connectionString">Stringa di connessione al database</param>
|
||||
/// <returns>Struttura gerarchica delle tabelle e delle loro colonne</returns>
|
||||
Task<IDictionary<string, IEnumerable<DbColumnInfo>>> GetDatabaseSchemaAsync(string connectionString);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using DataConnection.Interfaces;
|
||||
using DataConnection.EF;
|
||||
using DataConnection.EF.DatabaseDiscovery;
|
||||
using DataConnection.Enums;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Data_Coupler.Data
|
||||
{
|
||||
@@ -13,6 +14,8 @@ namespace Data_Coupler.Data
|
||||
{
|
||||
private readonly IDatabaseDiscovery _sqlServerDiscovery;
|
||||
private readonly IDatabaseDiscovery _mySqlDiscovery;
|
||||
private readonly DbManagerOptions _dbManagerOptions;
|
||||
private IDatabaseManager _databaseManager;
|
||||
|
||||
public DatabaseType SelectedDatabaseType { get; set; } = DatabaseType.SqlServer;
|
||||
public string ConnectionString { get; set; }
|
||||
@@ -22,9 +25,10 @@ namespace Data_Coupler.Data
|
||||
public bool IsConnected { get; private set; }
|
||||
public string ErrorMessage { get; private set; }
|
||||
|
||||
public DatabaseConnectionService()
|
||||
public DatabaseConnectionService(DbManagerOptions dbManagerOptions)
|
||||
{
|
||||
_sqlServerDiscovery = new SqlServerDatabaseDiscovery();
|
||||
_dbManagerOptions = dbManagerOptions ?? new DbManagerOptions();
|
||||
// Se in futuro verrà implementata la discovery MySQL, potremmo aggiungerla qui
|
||||
// _mySqlDiscovery = new MySqlDatabaseDiscovery();
|
||||
}
|
||||
@@ -104,5 +108,43 @@ namespace Data_Coupler.Data
|
||||
// Per altri tipi di database, implementare la logica appropriata
|
||||
return ConnectionString;
|
||||
}
|
||||
|
||||
public IDatabaseManager GetDatabaseManager()
|
||||
{
|
||||
if (_databaseManager != null)
|
||||
return _databaseManager;
|
||||
|
||||
// Configura le opzioni del database manager
|
||||
_dbManagerOptions.ServerConnectionString = ConnectionString;
|
||||
_dbManagerOptions.DatabaseName = SelectedDatabase;
|
||||
|
||||
// Configura il contesto in base al tipo di database
|
||||
_dbManagerOptions.DbContextConfigurator = options =>
|
||||
{
|
||||
switch (SelectedDatabaseType)
|
||||
{
|
||||
case DatabaseType.SqlServer:
|
||||
options.UseSqlServer(BuildConnectionStringWithDatabase(),
|
||||
sqlOptions => sqlOptions.CommandTimeout(_dbManagerOptions.CommandTimeout));
|
||||
break;
|
||||
// Aggiungi altri tipi di database quando implementati
|
||||
default:
|
||||
throw new NotSupportedException($"Tipo di database non supportato: {SelectedDatabaseType}");
|
||||
}
|
||||
};
|
||||
|
||||
// Crea il database manager
|
||||
_databaseManager = new EFCoreDatabaseManager(_dbManagerOptions);
|
||||
return _databaseManager;
|
||||
}
|
||||
|
||||
public void DisposeDatabaseManager()
|
||||
{
|
||||
if (_databaseManager != null)
|
||||
{
|
||||
_databaseManager.Dispose();
|
||||
_databaseManager = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,17 +241,19 @@
|
||||
databaseInfo = dbInfo;
|
||||
}
|
||||
|
||||
// Qui dovresti implementare la connessione al database selezionato
|
||||
// e recuperare le informazioni sullo schema
|
||||
// Per questo esempio, simuliamo che sia avvenuto con successo
|
||||
await Task.Delay(1000); // Simulazione operazione asincrona
|
||||
// Crea il database manager e connettiti al database selezionato
|
||||
var databaseManager = DatabaseService.GetDatabaseManager();
|
||||
|
||||
// Verifica la connessione al database specifico
|
||||
if (!await databaseManager.TestConnectionAsync())
|
||||
{
|
||||
throw new Exception($"Non è possibile connettersi al database {DatabaseService.SelectedDatabase}");
|
||||
}
|
||||
|
||||
// Recupera le informazioni sullo schema (tabelle e colonne)
|
||||
schemaInfo = await databaseManager.GetDatabaseSchemaAsync();
|
||||
|
||||
showSchemaInfo = true;
|
||||
// In un'implementazione reale, qui dovresti eseguire:
|
||||
// schemaInfo = await databaseManager.GetDatabaseSchemaAsync();
|
||||
|
||||
// Per ora creiamo dati di esempio
|
||||
schemaInfo = CreateSampleSchemaInfo();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -264,33 +266,4 @@
|
||||
isConnecting = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Metodo temporaneo per generare dati di esempio - da sostituire con dati reali
|
||||
private IDictionary<string, IEnumerable<DbColumnInfo>> CreateSampleSchemaInfo()
|
||||
{
|
||||
var result = new Dictionary<string, IEnumerable<DbColumnInfo>>();
|
||||
|
||||
// Tabella Customers
|
||||
var customerColumns = new List<DbColumnInfo>
|
||||
{
|
||||
new DbColumnInfo { Name = "Id", DataType = "int", IsPrimaryKey = true },
|
||||
new DbColumnInfo { Name = "Name", DataType = "nvarchar(100)" },
|
||||
new DbColumnInfo { Name = "Email", DataType = "nvarchar(255)" },
|
||||
new DbColumnInfo { Name = "Created", DataType = "datetime" }
|
||||
};
|
||||
|
||||
// Tabella Orders
|
||||
var orderColumns = new List<DbColumnInfo>
|
||||
{
|
||||
new DbColumnInfo { Name = "Id", DataType = "int", IsPrimaryKey = true },
|
||||
new DbColumnInfo { Name = "CustomerId", DataType = "int", IsForeignKey = true, ReferencedTable = "Customers", ReferencedColumn = "Id" },
|
||||
new DbColumnInfo { Name = "OrderDate", DataType = "datetime" },
|
||||
new DbColumnInfo { Name = "TotalAmount", DataType = "decimal(18,2)" }
|
||||
};
|
||||
|
||||
result.Add("Customers", customerColumns);
|
||||
result.Add("Orders", orderColumns);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
@page "/database-schema"
|
||||
@using DataConnection.Interfaces
|
||||
@using DataConnection.Enums
|
||||
@inject Data.DatabaseConnectionService DatabaseService
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<PageTitle>Schema del Database</PageTitle>
|
||||
|
||||
<h3>Schema del Database</h3>
|
||||
|
||||
@if (!DatabaseService.IsConnected || string.IsNullOrEmpty(DatabaseService.SelectedDatabase))
|
||||
{
|
||||
<div class="alert alert-warning">
|
||||
<p>Non sei connesso a nessun database. Devi prima stabilire una connessione.</p>
|
||||
<button class="btn btn-primary" @onclick="NavigateToConnection">Vai alla pagina di connessione</button>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span>Dettagli del Database: <strong>@DatabaseService.SelectedDatabase</strong></span>
|
||||
<button class="btn btn-outline-primary btn-sm" @onclick="RefreshSchema">
|
||||
<i class="oi oi-reload"></i> Aggiorna Schema
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (databaseInfo != null)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>Nome:</strong> @databaseInfo.Name
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<strong>Dimensione:</strong> @databaseInfo.SizeMB.ToString("N2") MB
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<strong>Creato il:</strong> @databaseInfo.CreationDate.ToString("dd/MM/yyyy HH:mm")
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<strong>Stato:</strong> @databaseInfo.Status
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Tabelle
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="list-group list-group-flush">
|
||||
<input type="text" class="form-control border-0 mb-2" placeholder="Filtra tabelle..." @oninput="FilterTables" />
|
||||
|
||||
@if (schemaInfo != null && schemaInfo.Count > 0)
|
||||
{
|
||||
@foreach (var table in filteredTables)
|
||||
{
|
||||
<button class="list-group-item list-group-item-action @(selectedTable == table.Key ? "active" : "")"
|
||||
@onclick="() => SelectTable(table.Key)">
|
||||
@table.Key
|
||||
</button>
|
||||
}
|
||||
}
|
||||
else if (isLoading)
|
||||
{
|
||||
<div class="text-center p-3">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Caricamento...</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group-item text-center text-muted">
|
||||
Nessuna tabella disponibile
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
@if (!string.IsNullOrEmpty(selectedTable))
|
||||
{
|
||||
<span>Struttura della tabella: <strong>@selectedTable</strong></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Seleziona una tabella</span>
|
||||
}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (!string.IsNullOrEmpty(selectedTable) && schemaInfo != null && schemaInfo.ContainsKey(selectedTable))
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Nome Colonna</th>
|
||||
<th>Tipo Dati</th>
|
||||
<th>Nullable</th>
|
||||
<th>Chiave</th>
|
||||
<th>Relazioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var column in schemaInfo[selectedTable])
|
||||
{
|
||||
<tr>
|
||||
<td>@column.Name</td>
|
||||
<td>@column.DataType</td>
|
||||
<td>
|
||||
@if (column.IsNullable)
|
||||
{
|
||||
<span class="badge bg-secondary">NULL</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="badge bg-danger">NOT NULL</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (column.IsPrimaryKey)
|
||||
{
|
||||
<span class="badge bg-primary">PK</span>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if (column.IsForeignKey)
|
||||
{
|
||||
<span class="badge bg-info text-dark">
|
||||
FK → @column.ReferencedTable.@column.ReferencedColumn
|
||||
</span>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else if (string.IsNullOrEmpty(selectedTable))
|
||||
{
|
||||
<div class="alert alert-info">
|
||||
Seleziona una tabella dal menu a sinistra per visualizzarne la struttura.
|
||||
</div>
|
||||
}
|
||||
else if (isLoading)
|
||||
{
|
||||
<div class="text-center">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Caricamento...</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-warning">
|
||||
Impossibile trovare informazioni sulla tabella selezionata.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool isLoading = false;
|
||||
private string selectedTable = "";
|
||||
private string tableFilter = "";
|
||||
private DatabaseInfo databaseInfo;
|
||||
private IDictionary<string, IEnumerable<DbColumnInfo>> schemaInfo;
|
||||
private IDictionary<string, IEnumerable<DbColumnInfo>> filteredTables;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (DatabaseService.IsConnected && !string.IsNullOrEmpty(DatabaseService.SelectedDatabase))
|
||||
{
|
||||
await LoadDatabaseSchema();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadDatabaseSchema()
|
||||
{
|
||||
try
|
||||
{
|
||||
isLoading = true;
|
||||
selectedTable = "";
|
||||
|
||||
// Ottieni informazioni sul database selezionato
|
||||
if (DatabaseService.DatabasesInfo.TryGetValue(DatabaseService.SelectedDatabase, out var dbInfo))
|
||||
{
|
||||
databaseInfo = dbInfo;
|
||||
}
|
||||
|
||||
// Crea il database manager e connettiti al database selezionato
|
||||
var databaseManager = DatabaseService.GetDatabaseManager();
|
||||
|
||||
// Verifica la connessione al database specifico
|
||||
if (await databaseManager.TestConnectionAsync())
|
||||
{
|
||||
// Recupera le informazioni sullo schema (tabelle e colonne)
|
||||
schemaInfo = await databaseManager.GetDatabaseSchemaAsync();
|
||||
filteredTables = schemaInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Non è possibile connettersi al database {DatabaseService.SelectedDatabase}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("console.error", "Errore caricamento schema:", ex.Message);
|
||||
//DatabaseService.ErrorMessage = $"Errore nel caricamento dello schema: {ex.Message}";
|
||||
schemaInfo = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectTable(string tableName)
|
||||
{
|
||||
selectedTable = tableName;
|
||||
}
|
||||
|
||||
private void FilterTables(ChangeEventArgs e)
|
||||
{
|
||||
tableFilter = e.Value?.ToString() ?? "";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tableFilter))
|
||||
{
|
||||
filteredTables = schemaInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredTables = schemaInfo
|
||||
.Where(t => t.Key.Contains(tableFilter, StringComparison.OrdinalIgnoreCase))
|
||||
.ToDictionary(t => t.Key, t => t.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshSchema()
|
||||
{
|
||||
await LoadDatabaseSchema();
|
||||
}
|
||||
|
||||
private void NavigateToConnection()
|
||||
{
|
||||
NavigationManager.NavigateTo("/database-connection");
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,11 @@
|
||||
<span class="oi oi-hard-drive" aria-hidden="true"></span> Database
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="database-schema">
|
||||
<span class="oi oi-list" aria-hidden="true"></span> Struttura Database
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user