using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using DataConnection.EF.SchemaProviders;
using DataConnection.Interfaces;
namespace DataConnection.DB;
///
/// Database manager per connessioni ODBC dirette (senza Entity Framework)
///
public class OdbcDatabaseManager : IDatabaseManager
{
private readonly string _connectionString;
private readonly OdbcSchemaProvider _schemaProvider;
private string _currentDatabase = string.Empty;
public OdbcDatabaseManager(string connectionString)
{
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
_schemaProvider = new OdbcSchemaProvider();
}
public async Task TestConnectionAsync()
{
try
{
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
return true;
}
catch
{
return false;
}
}
public Task> GetAsync(
Expression>? filter = null,
Func, IOrderedQueryable>? orderBy = null,
string includeProperties = "",
int? skip = null,
int? take = null) where T : class
{
throw new NotSupportedException("GetAsync with LINQ expressions is not supported for ODBC. Use ExecuteQueryAsync instead.");
}
public Task GetByIdAsync(object id) where T : class
{
throw new NotSupportedException("GetByIdAsync is not supported for ODBC. Use ExecuteQueryAsync with WHERE clause instead.");
}
public Task> ExecuteQueryAsync(string sql, params object[] parameters) where T : class
{
throw new NotSupportedException("ExecuteQueryAsync with entity type is not supported for ODBC. Use ExecuteRawQueryAsync instead.");
}
public async Task>> ExecuteRawQueryAsync(string sql, string databaseName = "", params object[] parameters)
{
var results = new List>();
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
// Cambia database se specificato
if (!string.IsNullOrEmpty(databaseName) && databaseName != _currentDatabase)
{
await connection.ChangeDatabaseAsync(databaseName);
_currentDatabase = databaseName;
}
using var command = new OdbcCommand(sql, connection);
// Aggiungi parametri
if (parameters != null && parameters.Length > 0)
{
for (int i = 0; i < parameters.Length; i++)
{
command.Parameters.Add(new OdbcParameter($"@p{i}", parameters[i] ?? DBNull.Value));
}
}
using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var row = new Dictionary();
for (int i = 0; i < reader.FieldCount; i++)
{
var fieldName = reader.GetName(i);
var value = reader.IsDBNull(i) ? DBNull.Value : reader.GetValue(i);
row[fieldName] = value;
}
results.Add(row);
}
return results;
}
public async Task ExecuteCommandAsync(string sql, params object[] parameters)
{
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
using var command = new OdbcCommand(sql, connection);
if (parameters != null && parameters.Length > 0)
{
for (int i = 0; i < parameters.Length; i++)
{
command.Parameters.Add(new OdbcParameter($"@p{i}", parameters[i] ?? DBNull.Value));
}
}
return await command.ExecuteNonQueryAsync();
}
public async Task> GetAvailableDatabasesAsync()
{
var databases = await _schemaProvider.GetAvailableDatabasesAsync(_connectionString);
return databases.ToList();
}
public async Task ChangeDatabaseAsync(string databaseName)
{
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
await connection.ChangeDatabaseAsync(databaseName);
_currentDatabase = databaseName;
}
public async Task>> GetDatabaseSchemaAsync()
{
return await _schemaProvider.GetDatabaseSchemaAsync(_connectionString);
}
public async Task> GetTableNamesAsync()
{
return await _schemaProvider.GetTableNamesAsync(_connectionString);
}
public async Task> GetTableSchemaAsync(string tableName)
{
return await _schemaProvider.GetTableSchemaAsync(_connectionString, tableName);
}
public async Task>> GetAllRecordsAsync(string tableName)
{
var query = $"SELECT * FROM {tableName}";
var results = await ExecuteRawQueryAsync(query);
return results;
}
public async Task GetPrimaryKeyFieldAsync(string tableName)
{
try
{
var schema = await GetTableSchemaAsync(tableName);
var pkColumn = schema.FirstOrDefault(c => c.IsPrimaryKey);
return pkColumn?.Name;
}
catch
{
return null;
}
}
public async Task>> ExecuteQueryAsync(string query, int? maxRows = null)
{
var results = new List>();
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
using var command = new OdbcCommand(query, connection);
if (maxRows.HasValue)
{
command.CommandText = WrapQueryWithLimit(query, maxRows.Value);
}
using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var row = new Dictionary();
for (int i = 0; i < reader.FieldCount; i++)
{
var fieldName = reader.GetName(i);
var value = reader.IsDBNull(i) ? null : reader.GetValue(i);
row[fieldName] = value;
}
results.Add(row);
}
return results;
}
public async Task ExecuteNonQueryAsync(string query)
{
using var connection = new OdbcConnection(_connectionString);
await connection.OpenAsync();
using var command = new OdbcCommand(query, connection);
return await command.ExecuteNonQueryAsync();
}
public async Task