Подключения не было закрыто, подключение открыто
помогите пожалуйста. Пишу код для учебной практики, вроде все норм но есть ошибка при включении программы Ошибка при получении множителя стадии.
Подключения не было закрыто, подключение открыто
Вроде везде где прописал подключения позакрывал, но всё равно эта ошибка. Извините за полотно
using System;
using System.Data.OleDb;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private OleDbConnection connection;
private OleDbCommand command;
private OleDbDataReader reader;
public Form1()
{
InitializeComponent();
InitializeDatabaseConnection();
LoadServiceNames();
LoadStageNames();
LoadSpecialists();
}
private void InitializeDatabaseConnection()
{
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Service.mdb";
connection = new OleDbConnection(connectionString);
command = new OleDbCommand();
command.Connection = connection;
}
private void LoadServiceNames()
{
try
{
connection.Open();
command.CommandText = "SELECT DISTINCT ServiceName FROM ServicePrices";
reader = command.ExecuteReader();
while (reader.Read())
{
serviceComboBox.Items.Add(reader["ServiceName"].ToString());
}
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при загрузке услуг: " + ex.Message);
}
finally
{
reader?.Close();
connection.Close();
}
}
private void LoadStageNames()
{
try
{
connection.Open();
command.CommandText = "SELECT StageName FROM Stage";
reader = command.ExecuteReader();
while (reader.Read())
{
stageComboBox.Items.Add(reader["StageName"].ToString());
}
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при загрузке стадий: " + ex.Message);
}
finally
{
reader?.Close();
connection.Close();
}
}
private void LoadSpecialists()
{
try
{
connection.Open();
command.CommandText = "SELECT DISTINCT SpecialistName FROM Specialist";
reader = command.ExecuteReader();
while (reader.Read())
{
specialistComboBox.Items.Add(reader["SpecialistName"].ToString());
}
specialistComboBox.SelectedIndexChanged += new EventHandler(OnSpecialistOrServiceChanged);
serviceComboBox.SelectedIndexChanged += new EventHandler(OnSpecialistOrServiceChanged);
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при загрузке специалистов: " + ex.Message);
}
finally
{
reader?.Close();
connection.Close();
}
}
private void OnSpecialistOrServiceChanged(object sender, EventArgs e)
{
CalculatePrice();
}
private void calculateButton_Click(object sender, EventArgs e)
{
CalculatePrice();
}
private void CalculatePrice()
{
try
{
if (serviceComboBox.SelectedItem == null || specialistComboBox.SelectedItem == null)
{
resultLabel.Text = "Ошибка: выберите и услугу, и специалиста.";
return;
}
connection.Open();
command.CommandText = "SELECT Price FROM ServicePrices WHERE ServiceName = @ServiceName AND SpecialistName = @SpecialistName";
command.Parameters.Clear();
command.Parameters.AddWithValue("@ServiceName", serviceComboBox.SelectedItem.ToString());
command.Parameters.AddWithValue("@SpecialistName", specialistComboBox.SelectedItem.ToString());
object result = command.ExecuteScalar();
if (result != null)
{
double hourlyRate = Convert.ToDouble(result);
string selectedStageName = stageComboBox.SelectedItem?.ToString();
double stageMultiplier = 1.0;
if (selectedStageName != null)
{
stageMultiplier = GetStageMultiplier(selectedStageName);
}
if (int.TryParse(hoursTextBox.Text, out int hours))
{
double totalPrice = hourlyRate * hours * stageMultiplier;
resultLabel.Text = $"{totalPrice:C}";
}
else
{
resultLabel.Text = "Ошибка: введите корректное количество часов.";
}
}
else
{
resultLabel.Text = "Ошибка: услуга не найдена.";
}
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при расчёте цены: " + ex.Message);
}
finally
{
connection.Close();
}
}
private double GetStageMultiplier(string stageName)
{
double stageMultiplier = 1.0;
try
{
connection.Open();
command.CommandText = "SELECT Multiplier FROM Stage WHERE StageName = @StageName";
command.Parameters.Clear();
command.Parameters.AddWithValue("@StageName", stageName);
object result = command.ExecuteScalar();
if (result != null)
{
stageMultiplier = Convert.ToDouble(result);
}
}
catch (Exception ex)
{
MessageBox.Show("Ошибка при получении множителя стадии: " + ex.Message);
}
finally
{
connection.Close();
}
return stageMultiplier;
}
}
}
Ответы (1 шт):
Исключение вероятно возникает потому что ваш код падает в конструкторе формы, и сборщик мусора пытается уничтожить открытое подключение. Перенесите запуск работы с базой данных в обработчик события Form.Load
и старайтесь больше не добавлять свой код в конструктор формы.
Кликните дважды в дизайнере по пустому месту на форме, появится обработчик
private void Form1_Load(obect sender, EventArgs e)
{
// сюда перенесите код из конструктора формы
}
В конструкторе должен остаться только InitializeComponent()
.
Не нужно переиспользовать OleDb...
классы, в этом нет смысла, вы не выиграете так ни в производительности, не в потреблении памяти.
Если нужно за одно подключение отработать с базой, откройте подключение один раз и в конце работ закройте.
Команду OleDbCommand
лучше создавать на каждый запрос новую, чтобы избежать сайд-эффектов у отработанных команд. Вы можете в будущем забыть потереть параметры или ещё что-нибудь.
Также не забывать что и подключение, и команда, и ридер реализуют IDisposable
. Поэтому воспользуйтесь ключевым словом using
вместо вызовов .Close()
или .Dispose()
.