Prima implementazione del servizio di connessione e scoperta del database
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
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;
|
||||
|
||||
namespace Data_Coupler.Data
|
||||
{
|
||||
public class DatabaseConnectionService
|
||||
{
|
||||
private readonly IDatabaseDiscovery _sqlServerDiscovery;
|
||||
private readonly IDatabaseDiscovery _mySqlDiscovery;
|
||||
|
||||
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()
|
||||
{
|
||||
_sqlServerDiscovery = new SqlServerDatabaseDiscovery();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,8 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataConnection\DataConnection.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
@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;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
showSchemaInfo = true;
|
||||
// In un'implementazione reale, qui dovresti eseguire:
|
||||
// schemaInfo = await databaseManager.GetDatabaseSchemaAsync();
|
||||
|
||||
// Per ora creiamo dati di esempio
|
||||
schemaInfo = CreateSampleSchemaInfo();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Data_Coupler.Data;
|
||||
using DataConnection;
|
||||
using DataConnection.EF;
|
||||
using DataConnection.Interfaces;
|
||||
using DataConnection.EF.DatabaseDiscovery;
|
||||
using DataConnection.Enums;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -9,8 +16,16 @@ builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddSingleton<WeatherForecastService>();
|
||||
|
||||
// Registra il servizio di connessione al database
|
||||
builder.Services.AddScoped<DatabaseConnectionService>();
|
||||
|
||||
// Registriamo i servizi di database discovery
|
||||
builder.Services.AddSingleton<IDatabaseDiscovery, SqlServerDatabaseDiscovery>();
|
||||
builder.Services.AddSingleton<DbManagerOptions>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
@@ -29,3 +44,4 @@ app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
|
||||
app.Run();
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="database-connection">
|
||||
<span class="oi oi-hard-drive" aria-hidden="true"></span> Database
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
|
||||
<clear />
|
||||
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user