-Rimozione dei file non più necessari
This commit is contained in:
@@ -1,150 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DataConnection.Interfaces;
|
|
||||||
using DataConnection.EF;
|
|
||||||
using DataConnection.EF.DatabaseDiscovery;
|
|
||||||
using DataConnection.Enums;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Data_Coupler.Data
|
|
||||||
{
|
|
||||||
public class DatabaseConnectionService
|
|
||||||
{
|
|
||||||
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; }
|
|
||||||
public List<string> AvailableDatabases { get; private set; } = new List<string>();
|
|
||||||
public Dictionary<string, DatabaseInfo> DatabasesInfo { get; private set; } = new Dictionary<string, DatabaseInfo>();
|
|
||||||
public string SelectedDatabase { get; set; }
|
|
||||||
public bool IsConnected { get; private set; }
|
|
||||||
public string ErrorMessage { get; private set; }
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDatabaseDiscovery GetDatabaseDiscovery()
|
|
||||||
{
|
|
||||||
return SelectedDatabaseType switch
|
|
||||||
{
|
|
||||||
DatabaseType.SqlServer => _sqlServerDiscovery,
|
|
||||||
// DatabaseType.MySql => _mySqlDiscovery,
|
|
||||||
_ => throw new NotSupportedException($"Tipo di database non supportato: {SelectedDatabaseType}")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> TestConnectionAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var discovery = GetDatabaseDiscovery();
|
|
||||||
AvailableDatabases = await discovery.GetAvailableDatabasesAsync(ConnectionString, true);
|
|
||||||
IsConnected = AvailableDatabases.Any();
|
|
||||||
ErrorMessage = IsConnected ? null : "Nessun database trovato sul server.";
|
|
||||||
return IsConnected;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
IsConnected = false;
|
|
||||||
ErrorMessage = $"Errore di connessione: {ex.Message}";
|
|
||||||
if (ex.InnerException != null)
|
|
||||||
{
|
|
||||||
ErrorMessage += $" - {ex.InnerException.Message}";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Dictionary<string, DatabaseInfo>> GetDatabasesInfoAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var discovery = GetDatabaseDiscovery();
|
|
||||||
DatabasesInfo = await discovery.GetDatabasesInfoAsync(ConnectionString, false);
|
|
||||||
return DatabasesInfo;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
ErrorMessage = $"Errore nel recupero delle informazioni: {ex.Message}";
|
|
||||||
return new Dictionary<string, DatabaseInfo>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string BuildConnectionStringWithDatabase()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(SelectedDatabase))
|
|
||||||
return ConnectionString;
|
|
||||||
|
|
||||||
// Per SQL Server
|
|
||||||
if (SelectedDatabaseType == DatabaseType.SqlServer)
|
|
||||||
{
|
|
||||||
if (ConnectionString.Contains("Initial Catalog=") || ConnectionString.Contains("Database="))
|
|
||||||
{
|
|
||||||
// Sostituisci il database esistente
|
|
||||||
var modifiedString = System.Text.RegularExpressions.Regex.Replace(
|
|
||||||
ConnectionString,
|
|
||||||
@"(Initial Catalog|Database)=([^;]*)",
|
|
||||||
$"$1={SelectedDatabase}");
|
|
||||||
|
|
||||||
return modifiedString;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Aggiungi il database
|
|
||||||
return ConnectionString + $";Database={SelectedDatabase}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
@page "/database-connection"
|
|
||||||
@using DataConnection.Enums
|
|
||||||
@using DataConnection.Interfaces
|
|
||||||
@inject Data.DatabaseConnectionService DatabaseService
|
|
||||||
@inject IJSRuntime JSRuntime
|
|
||||||
|
|
||||||
<PageTitle>Connessione al Database</PageTitle>
|
|
||||||
|
|
||||||
<h3>Connessione al Database</h3>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
Configurazione connessione
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="databaseType" class="form-label">Tipo di Database</label>
|
|
||||||
<select id="databaseType" class="form-select" @bind="DatabaseService.SelectedDatabaseType">
|
|
||||||
<option value="@DatabaseType.SqlServer">SQL Server</option>
|
|
||||||
<option value="@DatabaseType.MySql">MySQL</option>
|
|
||||||
<option value="@DatabaseType.PostgreSql">PostgreSQL</option>
|
|
||||||
<option value="@DatabaseType.Oracle">Oracle</option>
|
|
||||||
<option value="@DatabaseType.Sqlite">SQLite</option>
|
|
||||||
<option value="@DatabaseType.DB2">DB2</option>
|
|
||||||
<option value="@DatabaseType.SapHana">SAP HANA</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="connectionString" class="form-label">Stringa di Connessione</label>
|
|
||||||
<input id="connectionString" class="form-control" @bind="DatabaseService.ConnectionString" placeholder="Es. Server=localhost;User Id=sa;Password=password;TrustServerCertificate=True" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-grid gap-2">
|
|
||||||
<button class="btn btn-primary" @onclick="TestConnection" disabled="@isLoading">
|
|
||||||
@if (isLoading)
|
|
||||||
{
|
|
||||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
||||||
<span> Connessione in corso...</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span>Test Connessione</span>
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (DatabaseService.ErrorMessage != null)
|
|
||||||
{
|
|
||||||
<div class="alert alert-danger mt-3">
|
|
||||||
@DatabaseService.ErrorMessage
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (DatabaseService.IsConnected)
|
|
||||||
{
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
Database Disponibili
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="selectDatabase" class="form-label">Seleziona Database</label>
|
|
||||||
<select id="selectDatabase" class="form-select" @bind="DatabaseService.SelectedDatabase">
|
|
||||||
<option value="">-- Seleziona un database --</option>
|
|
||||||
@foreach (var db in DatabaseService.AvailableDatabases)
|
|
||||||
{
|
|
||||||
<option value="@db">@db</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (!string.IsNullOrEmpty(DatabaseService.SelectedDatabase) && databaseInfo != null)
|
|
||||||
{
|
|
||||||
<div class="mt-3">
|
|
||||||
<h5>Dettagli Database</h5>
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th>Nome</th>
|
|
||||||
<td>@databaseInfo?.Name</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Dimensione</th>
|
|
||||||
<td>@databaseInfo?.SizeMB MB</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Data Creazione</th>
|
|
||||||
<td>@databaseInfo?.CreationDate.ToString("dd/MM/yyyy HH:mm")</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Stato</th>
|
|
||||||
<td>@databaseInfo?.Status</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Proprietario</th>
|
|
||||||
<td>@databaseInfo?.Owner</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div class="d-grid gap-2 mt-3">
|
|
||||||
<button class="btn btn-success" @onclick="ConnectToDatabase" disabled="@isConnecting">
|
|
||||||
@if (isConnecting)
|
|
||||||
{
|
|
||||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
||||||
<span> Connessione in corso...</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span>Connetti al Database</span>
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (showSchemaInfo)
|
|
||||||
{
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
Schema del Database: @DatabaseService.SelectedDatabase
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
@if (schemaInfo != null && schemaInfo.Count > 0)
|
|
||||||
{
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-striped table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Tabella</th>
|
|
||||||
<th>Colonne</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach (var table in schemaInfo)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>@table.Key</td>
|
|
||||||
<td>
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
@foreach (var column in table.Value)
|
|
||||||
{
|
|
||||||
<li>
|
|
||||||
<strong>@column.Name</strong>
|
|
||||||
<span class="text-muted">(@column.DataType)</span>
|
|
||||||
@if (column.IsPrimaryKey)
|
|
||||||
{
|
|
||||||
<span class="badge bg-primary">PK</span>
|
|
||||||
}
|
|
||||||
@if (column.IsForeignKey)
|
|
||||||
{
|
|
||||||
<span class="badge bg-info">FK → @column.ReferencedTable</span>
|
|
||||||
}
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="alert alert-info">
|
|
||||||
Nessuna informazione sullo schema disponibile.
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private bool isLoading = false;
|
|
||||||
private bool isConnecting = false;
|
|
||||||
private bool showSchemaInfo = false;
|
|
||||||
private DatabaseInfo databaseInfo;
|
|
||||||
private IDictionary<string, IEnumerable<DbColumnInfo>> schemaInfo;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
// Puoi impostare valori predefiniti, magari da configurazione
|
|
||||||
DatabaseService.ConnectionString = "Server=localhost;User Id=sa;Password=password;TrustServerCertificate=True";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task TestConnection()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
isLoading = true;
|
|
||||||
showSchemaInfo = false;
|
|
||||||
databaseInfo = null;
|
|
||||||
|
|
||||||
await DatabaseService.TestConnectionAsync();
|
|
||||||
|
|
||||||
if (DatabaseService.IsConnected)
|
|
||||||
{
|
|
||||||
await DatabaseService.GetDatabasesInfoAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await JSRuntime.InvokeVoidAsync("console.error", "Errore connessione:", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
isLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ConnectToDatabase()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(DatabaseService.SelectedDatabase))
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
isConnecting = true;
|
|
||||||
showSchemaInfo = false;
|
|
||||||
|
|
||||||
// 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())
|
|
||||||
{
|
|
||||||
throw new Exception($"Non è possibile connettersi al database {DatabaseService.SelectedDatabase}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recupera le informazioni sullo schema (tabelle e colonne)
|
|
||||||
schemaInfo = await databaseManager.GetDatabaseSchemaAsync();
|
|
||||||
|
|
||||||
showSchemaInfo = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await JSRuntime.InvokeVoidAsync("console.error", "Errore connessione database:", ex.Message);
|
|
||||||
//DatabaseService.ErrorMessage = $"Errore nella connessione al database: {ex.Message}";
|
|
||||||
showSchemaInfo = false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
isConnecting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
@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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
@page "/rest-discovery"
|
|
||||||
@using DataConnection.REST.Configuration
|
|
||||||
@using DataConnection.REST.Implementations
|
|
||||||
@using DataConnection.REST.Models
|
|
||||||
@using System.Net.Http
|
|
||||||
@inject IHttpClientFactory HttpClientFactory
|
|
||||||
|
|
||||||
<h3>REST Service Discovery</h3>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="serviceType" class="form-label">Service Type:</label>
|
|
||||||
<select id="serviceType" class="form-select" @bind="SelectedServiceType">
|
|
||||||
<option value="">-- Select Service --</option>
|
|
||||||
<option value="SAPB1">SAP Business One Service Layer</option>
|
|
||||||
@* Add other service types here later *@
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@if (SelectedServiceType == "SAPB1")
|
|
||||||
{
|
|
||||||
<div class="card mb-3">
|
|
||||||
<div class="card-header">SAP Business One Connection Details</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="baseUrl" class="form-label">Service Layer Base URL:</label>
|
|
||||||
<input type="text" id="baseUrl" class="form-control" @bind="SapB1Options.BaseUrl" placeholder="e.g., https://sap-server:50000" />
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="companyDb" class="form-label">Company DB:</label>
|
|
||||||
<input type="text" id="companyDb" class="form-control" @bind="SapB1Options.CompanyDb" />
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="username" class="form-label">Username:</label>
|
|
||||||
<input type="text" id="username" class="form-control" @bind="SapB1Options.Username" />
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="password" class="form-label">Password:</label>
|
|
||||||
<input type="password" id="password" class="form-control" @bind="SapB1Options.Password" />
|
|
||||||
</div>
|
|
||||||
<div class="form-check mb-3">
|
|
||||||
<input class="form-check-input" type="checkbox" id="ignoreSsl" @bind="SapB1Options.IgnoreSslErrors">
|
|
||||||
<label class="form-check-label" for="ignoreSsl">
|
|
||||||
Ignore SSL Errors (Use with caution)
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-primary" @onclick="HandleConnectClick" disabled="IsLoading">
|
|
||||||
@if (IsLoading)
|
|
||||||
{
|
|
||||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
|
||||||
<span> Connecting...</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span>Connect and Discover Entities</span>
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!string.IsNullOrEmpty(StatusMessage))
|
|
||||||
{
|
|
||||||
<div class="alert @StatusMessageClass mt-3" role="alert">
|
|
||||||
@StatusMessage
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (DiscoveredEntities.Any())
|
|
||||||
{
|
|
||||||
<h4 class="mt-4">Discovered Entities</h4>
|
|
||||||
<div style="max-height: 500px; overflow-y: auto;">
|
|
||||||
<ul class="list-group">
|
|
||||||
@foreach (var entity in DiscoveredEntities.OrderBy(e => e.Name))
|
|
||||||
{
|
|
||||||
<li class="list-group-item">
|
|
||||||
<h5>@entity.Name</h5>
|
|
||||||
<ul class="list-unstyled ms-3">
|
|
||||||
@foreach (var prop in entity.Properties.OrderBy(p => p.Name))
|
|
||||||
{
|
|
||||||
<li>
|
|
||||||
<code>@prop.Name</code> (@prop.Type) @(prop.IsKey ? "[Key]" : "")
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private string SelectedServiceType { get; set; } = "";
|
|
||||||
private SapB1ConnectionOptions SapB1Options { get; set; } = new SapB1ConnectionOptions();
|
|
||||||
private List<RestEntityInfo> DiscoveredEntities { get; set; } = new List<RestEntityInfo>();
|
|
||||||
private bool IsLoading { get; set; } = false;
|
|
||||||
private string? StatusMessage { get; set; }
|
|
||||||
private string StatusMessageClass => !string.IsNullOrEmpty(StatusMessage) && StatusMessage.StartsWith("Error") ? "alert-danger" : "alert-success";
|
|
||||||
|
|
||||||
// Helper class to hold SAP B1 specific inputs
|
|
||||||
private class SapB1ConnectionOptions
|
|
||||||
{
|
|
||||||
public string? BaseUrl { get; set; }
|
|
||||||
public string? CompanyDb { get; set; }
|
|
||||||
public string? Username { get; set; }
|
|
||||||
public string? Password { get; set; }
|
|
||||||
public bool IgnoreSslErrors { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task HandleConnectClick()
|
|
||||||
{
|
|
||||||
IsLoading = true;
|
|
||||||
StatusMessage = null;
|
|
||||||
DiscoveredEntities.Clear();
|
|
||||||
StateHasChanged(); // Update UI to show loading
|
|
||||||
|
|
||||||
if (SelectedServiceType == "SAPB1")
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(SapB1Options.BaseUrl) ||
|
|
||||||
string.IsNullOrWhiteSpace(SapB1Options.CompanyDb) ||
|
|
||||||
string.IsNullOrWhiteSpace(SapB1Options.Username) ||
|
|
||||||
string.IsNullOrWhiteSpace(SapB1Options.Password))
|
|
||||||
{
|
|
||||||
StatusMessage = "Error: Please fill in all SAP Business One connection details.";
|
|
||||||
IsLoading = false;
|
|
||||||
StateHasChanged();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var restOptions = new RestServiceOptions
|
|
||||||
{
|
|
||||||
BaseUrl = SapB1Options.BaseUrl,
|
|
||||||
IgnoreSslErrors = SapB1Options.IgnoreSslErrors
|
|
||||||
// Username/Password are not set here as SapB1ServiceClient handles them in LoginAsync
|
|
||||||
};
|
|
||||||
|
|
||||||
// SapB1ServiceClient manages its own HttpClient internally for cookie handling
|
|
||||||
// We don't inject HttpClient directly into it via constructor in this setup.
|
|
||||||
// The BaseRestServiceClient constructor receives an HttpClient, but SapB1ServiceClient
|
|
||||||
// creates its own specific one in CreateConfiguredHttpClient.
|
|
||||||
// We pass the factory-created client to the base, but the SapB1 specific logic uses its own.
|
|
||||||
// This seems slightly complex, might need refactoring later, but follows current implementation.
|
|
||||||
|
|
||||||
// Let's simplify: Create the client directly here for now.
|
|
||||||
var client = new SapB1ServiceClient(restOptions);
|
|
||||||
|
|
||||||
StatusMessage = "Attempting login...";
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
bool loggedIn = await client.LoginAsync(SapB1Options.CompanyDb, SapB1Options.Username, SapB1Options.Password);
|
|
||||||
|
|
||||||
if (loggedIn)
|
|
||||||
{
|
|
||||||
StatusMessage = "Login successful. Discovering entities...";
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
DiscoveredEntities = await client.DiscoverEntitiesAsync();
|
|
||||||
|
|
||||||
if (DiscoveredEntities.Any())
|
|
||||||
{
|
|
||||||
StatusMessage = $"Discovery complete. Found {DiscoveredEntities.Count} entities.";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StatusMessage = "Login successful, but failed to discover entities or no entities found.";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: Logout after discovery if desired
|
|
||||||
// await client.LogoutAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StatusMessage = "Error: SAP B1 Login failed. Check credentials and Service Layer status.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Log the full exception details somewhere appropriate
|
|
||||||
Console.WriteLine($"Error during SAP B1 connection/discovery: {ex}");
|
|
||||||
StatusMessage = $"Error: An exception occurred: {ex.Message}";
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IsLoading = false;
|
|
||||||
StateHasChanged(); // Update UI after completion/error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StatusMessage = "Error: Please select a service type.";
|
|
||||||
IsLoading = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user