Нужно подключить БД к .Net WinForm проекту.
Реализация проекта должна быть с использованием PostgreSQL, поэтому выбрал Supabase.
Проблема в том, что как бы я не пытался, все время выдает одну и ту же ошибку
Запрошенное имя верно, но данные запрошенного типа не найдены
. Пробовал разные способы, но не помогало. На скрине полный стек с ошибками.
Какие есть идеи?
appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=db.chrbzfqlxbywuqbouoxe.supabase.co;Port=5432;Database=postgres;Username=postgres;Password=********;SSL Mode=Require;Trust Server Certificate=true"
}
}
Подключение к БД:
using Microsoft.Extensions.Configuration;
using Npgsql;
using System.Data;
namespace FitnessCenterManagement;
public class DatabaseConnection : IDisposable
{
private readonly string _connectionString;
private NpgsqlConnection? _connection;
public DatabaseConnection()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
_connectionString = configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string not found in configuration.");
}
public async Task<NpgsqlConnection> GetConnectionAsync()
{
if (_connection == null || _connection.State != ConnectionState.Open)
{
_connection = new NpgsqlConnection(_connectionString);
await _connection.OpenAsync();
}
return _connection;
}
public async Task CloseConnectionAsync()
{
if (_connection != null && _connection.State == ConnectionState.Open)
{
await _connection.CloseAsync();
await _connection.DisposeAsync();
_connection = null;
}
}
public async Task<int> ExecuteNonQueryAsync(string sql, params NpgsqlParameter[] parameters)
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync();
await using var command = new NpgsqlCommand(sql, connection);
if (parameters.Length > 0)
command.Parameters.AddRange(parameters);
return await command.ExecuteNonQueryAsync();
}
public async Task<DataTable> ExecuteQueryAsync(string sql, params NpgsqlParameter[] parameters)
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync();
await using var command = new NpgsqlCommand(sql, connection);
if (parameters.Length > 0)
command.Parameters.AddRange(parameters);
var dataTable = new DataTable();
using var reader = await command.ExecuteReaderAsync();
dataTable.Load(reader);
return dataTable;
}
public async Task<bool> UserExistsAsync(string login)
{
var sql = "SELECT COUNT(1) FROM fitness_centers WHERE login = @login";
var parameters = new NpgsqlParameter[]
{
new("@login", login)
};
var result = await ExecuteQueryAsync(sql, parameters);
return Convert.ToInt32(result.Rows[0][0]) > 0;
}
public async Task<bool> RegisterFitnessCenterAsync(string name, string login, string password, string address)
{
try
{
var existsSql = "SELECT COUNT(1) FROM fitness_centers WHERE login = @login";
var existsParams = new NpgsqlParameter[]
{
new("@login", login)
};
var existsResult = await ExecuteQueryAsync(existsSql, existsParams);
var count = Convert.ToInt32(existsResult.Rows[0][0]);
if (count > 0)
{
Console.WriteLine($"User with login '{login}' already exists");
return false;
}
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(password);
var insertSql = @"
INSERT INTO fitness_centers (name, login, password, address, created_at)
VALUES (@name, @login, @password, @address, @created_at)";
var insertParams = new NpgsqlParameter[]
{
new("@name", name),
new("@login", login),
new("@password", hashedPassword),
new("@address", address),
new("@created_at", DateTime.UtcNow)
};
var rowsAffected = await ExecuteNonQueryAsync(insertSql, insertParams);
Console.WriteLine($"Registration: {rowsAffected} rows affected");
return rowsAffected > 0;
}
catch (PostgresException pgEx)
{
Console.WriteLine($"PostgreSQL Error: {pgEx.SqlState} - {pgEx.MessageText}");
Console.WriteLine($"Detail: {pgEx.Detail}");
throw;
}
catch (Exception ex)
{
Console.WriteLine($"General Error: {ex.Message}");
Console.WriteLine($"StackTrace: {ex.StackTrace}");
throw;
}
}
public void Dispose()
{
if (_connection != null)
{
if (_connection.State == ConnectionState.Open)
_connection.Close();
_connection.Dispose();
}
}
}
Использование:
using System;
using System.Data;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Extensions.Configuration;
using Npgsql;
namespace FitnessCenterManagement
{
public partial class RegistrationMenuForm : Form
{
public RegistrationMenuForm()
{
InitializeComponent();
_dbConnection = new DatabaseConnection();
CenterUI();
ApplyColorScheme();
WireUpEvents();
}
private void ApplyColorScheme()
{
// Цвета
}
private void WireUpEvents()
{
_registerButton.Click += OnRegisterButtonClick;
_backButton.Click += OnBackButtonClick;
this.KeyPreview = true;
this.KeyDown += OnFormKeyDown;
}
private async void OnRegisterButtonClick(object? sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(_nameTextBox.Text) ||
string.IsNullOrWhiteSpace(_loginTextBox.Text) ||
string.IsNullOrWhiteSpace(_passwordTextBox.Text) ||
string.IsNullOrWhiteSpace(_addressTextBox.Text))
{
MessageBox.Show("Пожалуйста, заполните все поля", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (_passwordTextBox.Text.Length < 6)
{
MessageBox.Show("Пароль должен содержать минимум 6 символов", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
_registerButton.Enabled = false;
_registerButton.Text = "Регистрация...";
try
{
bool success = await _dbConnection.RegisterFitnessCenterAsync(
_nameTextBox.Text.Trim(),
_loginTextBox.Text.Trim(),
_passwordTextBox.Text,
_addressTextBox.Text.Trim()
);
if (success)
{
MessageBox.Show("Регистрация успешно завершена!", "Успех",
MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Close();
}
else
{
MessageBox.Show("Пользователь с таким логином уже существует", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (PostgresException pgEx)
{
string errorMessage = pgEx.SqlState switch
{
"23505" => "Пользователь с таким логином уже существует",
"28P01" => "Ошибка аутентификации. Проверьте пароль подключения",
"3D000" => "База данных не найдена",
"08006" => "Соединение разорвано. Проверьте настройки сети",
_ => $"Ошибка базы данных: {pgEx.Message}"
};
MessageBox.Show(errorMessage, "Ошибка базы данных",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
Console.WriteLine($"General Error: {ex.Message}");
Console.WriteLine($"StackTrace: {ex.StackTrace}");
MessageBox.Show($"Ошибка при регистрации: {ex.Message}.\nОшибка стека: {ex.StackTrace}", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
_registerButton.Enabled = true;
_registerButton.Text = "Зарегистрировать";
}
}
private void OnBackButtonClick(object? sender, EventArgs e)
{
this.Close();
}
private void OnFormKeyDown(object? sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && e.Control)
{
OnRegisterButtonClick(this, EventArgs.Empty);
}
else if (e.KeyCode == Keys.Escape)
{
this.Close();
}
}
}
}
P.S. Я знаю, что есть отдельная библиотека Supabase для C#, но у меня задание, реализовать в таком формате.
Ошибка -