Reputation: 7025
Could someone give me some tips related with release resources (memory resources)? I'm just a student and I'm building a system to an hypothetical small market, and during the testing of the option that add new products to cart, I discovered - using the Task Manager - that something is holding the resources, because the memory used by the program during debugging is increased in some bytes after every time I click on a specific button.
I'd like to know what I'm doing wrong, I also used dispose to release the resources used to connect with the database. Please help me, you don't have to code anything for me, just explain me what else should I release.
The button I'm referring to above is the buttonAdicionar
it's event is at, buttonAdicionar_Click
.
Here is the code at pastebin if you could take a look: pastebin.com/CdJbJAqc
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace Projeto_TCC
{
public partial class FormCaixa : Form
{
#region Campos
// const string CONNECTION_STRING = "server=localhost;uid=root;pwd=root;database=Projeto_TCC";
private string mensagemDeSaida = "finalizar da aplicação";
private int item = 0;
private double totalVenda = 0.0;
#endregion
#region Método construtor
public FormCaixa()
{
InitializeComponent();
}
#endregion
#region Evento Click do ToolStrip Encerrar sessão
private void encerrarSessãoToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Yes;
mensagemDeSaida = "encerrar esta sessão";
this.Close();
}
#endregion
#region Evento Click do ToolStrip Sair
private void sairToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
#endregion
#region Evento Click do ToolStrip Sobre
private void sobreToolStripMenuItem_Click(object sender, EventArgs e)
{
new AboutBoxProjeto().ShowDialog(); // Isso é uma boa prática?
}
#endregion
#region Evento FormClosing do FormCaixa
private void FormCaixa_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Deseja " + mensagemDeSaida + "?", "Caixa", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
e.Cancel = true;
mensagemDeSaida = "finalizar da aplicação";
}
#endregion
#region Evento Click do Button Adicionar
private void buttonAdicionar_Click(object sender, EventArgs e)
{
// Prepara a conexão com o DB
MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString);
// Objetos utilizado para a realização de alguns processos
MySqlDataAdapter da = new MySqlDataAdapter();
DataTable dt = new DataTable();
// Prepara o comando em SQL que retorná os dados sobre o item a ser adicionado à lista
MySqlCommand cmd = new MySqlCommand("SELECT codigo, descricao, unidMedida, vlUnitario FROM tabEstoque WHERE codBar = @codBar;", con);
cmd.Parameters.Add("@codBar", MySqlDbType.VarChar).Value = textBoxCodBarras.Text;
try
{
// Abre a conexão e executa o comando em SQL
con.Open();
da.SelectCommand = cmd;
da.SelectCommand.ExecuteNonQuery();
da.Fill(dt);
// Caso haja alguma linha no DataSet ds então existe um produto com o codigo de barra procurado no banco de dados
if (dt.Rows.Count == 1)
{
bool itemIgual = false;
int rowIndex = 0;
// Passa por todas as linhas da lista de compras para verificar se existe outro item igual
foreach (DataGridViewRow dgvListaRow in dataGridViewLista.Rows)
{
// Verifica se o produto da linha da lista de compra é o mesmo do código de barras
if (dgvListaRow.Cells[1].FormattedValue.ToString() == dt.Rows[0][0].ToString())
{
// Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
if (!this.VerificarSeExcede(Convert.ToInt32(dgvListaRow.Cells[1].FormattedValue), Convert.ToInt32(dgvListaRow.Cells[3].FormattedValue) + 1))
{
// Adiciona mais um na quantidade do item na lista de compra
dgvListaRow.Cells[3].Value = Convert.ToInt32(dgvListaRow.Cells[3].FormattedValue) + 1;
// Multiplica o VL. ITEM. pela nova quantidade e armazena o resultado em VL. ITEM
dgvListaRow.Cells[6].Value = String.Format("{0:f}",
(Convert.ToDouble(dgvListaRow.Cells[3].Value) * Convert.ToDouble(dgvListaRow.Cells[5].Value)));
// Adiciona o valor do produto ao valor total da venda
totalVenda += Convert.ToDouble(dgvListaRow.Cells[5].Value);
}
else
{
MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
itemIgual = true; // Evita que o if abaixo seja executado
break; // Sai do loop para econimizar tempo no processamento
}
rowIndex++;
}
// Caso o item não seja igual a nenhum outro na lista ele é adicionado à lista
if (!itemIgual)
{
// Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
if (!this.VerificarSeExcede(Convert.ToInt32(dt.Rows[0][0].ToString()), 1))
{
dataGridViewLista.Rows.Add(
++item, // ITEM
dt.Rows[0][0], // CÓDIGO
dt.Rows[0][1], // DESCRIÇÃO
1, // QTD.
dt.Rows[0][2], // UN.
dt.Rows[0][3], // VL. UNIT.
dt.Rows[0][3]); // VL. ITEM.
// Adiciona o valor do produto ao valor total da venda
totalVenda += Convert.ToDouble(dt.Rows[0][3].ToString());
}
else
{
MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// Atualiza a label que o exibe o total da venda
labelTotal.Text = String.Format("Total: {0:c}", totalVenda);
}
else // Mensagem exibida caso a cosulta nao retorne alguma coisa
{
MessageBox.Show("Este item não consta no banco de dados.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (MySqlException ex)
{
MessageBox.Show("Ocorreu um erro durante a comunicação com o banco de dados.\n\n" + ex.Message, "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
con.Close(); // Fecha a conexão
// Liberam os recursos/espaços ocupados na memória
da.Dispose();
dt.Dispose();
cmd.Dispose();
}
//textBoxCodBarras.Clear();
//textBoxCodBarras.Focus();
}
#endregion
private bool VerificarSeExcede(int codProd, int quantItem)
{
MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString);
MySqlCommand cmd = new MySqlCommand("SELECT codigo, quantidade FROM tabestoque WHERE codigo = @codProd", con);
cmd.Parameters.Add("@codProd", MySqlDbType.Int32).Value = codProd;
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
con.Open();
da.SelectCommand.ExecuteNonQuery();
da.Fill(dt);
int quantDB = Convert.ToInt32(dt.Rows[0][1]);
con.Close();
cmd.Dispose();
da.Dispose();
dt.Dispose();
// Verifica se a quantidade do produto no banco de dados é >= que a quantidade do item na lista
if (quantDB >= quantItem)
return false;
else
return true;
}
}
}
Thanks.
Upvotes: 2
Views: 256
Reputation: 401
My best guess would be by starting to use the using
tags in C#
instead of
myConnection = new connection(connectionString);
myConnection.open();
//do something with connection
myconnection.close();
you should try:
using (connection myConnection = new connection(connectionstring))
{
//do something with myConnection
}
Also, make your buttons so that its not calling DB injecting code directly, but use a Control class.
Eg on
`private void buttonAdicionar_Click(object sender, EventArgs e)`
{
controlClass.DoSomethingNow()
}
and in your control class the following method:
controlClass :class
{
//make singleton?
public void DoSomethingNow()
{
using (connection myConnection = new connection(connectionstring))
{
//do something with myConnection
}
}
}
This way you exactly know when you're using what. Your IDE, like Visual Studio, might help you relocate code for better performance, based on tips form the compiler.
Also, as a general tip, try to read up on Design Patterns. these patterns aren't limited to C# so it's a nice to know / must know later on.
Upvotes: 2
Reputation: 4156
You are not doing anything inherently wrong, as a quick test you might want to change the order when you are closing/disposing leaving the command and connection for last.
da.Dispose();
dt.Dispose();
cmd.Dispose();
con.Close();
Not sure this will fix your problem, if you adapt using() as suggested elsewhere you will get the right order automatically.
Another thing I noticed is that you use DataAdapter and DataTable but they don't really add any value, these two just add unnecessary memory overhead, try using DataReader instead. Example with using() and DataReader:
private bool VerificarSeExcede(int codProd, int quantItem)
{
using(var con = new MySqlConnection(Properties.Settings.Default.ConnectionString))
{
using(var cmd = new MySqlCommand("SELECT codigo, quantidade FROM tabestoque WHERE codigo = @codProd", con))
{
cmd.Parameters.Add("@codProd", MySqlDbType.Int32).Value = codProd;
con.open();
using(var reader = cmd.ExecuteReader())
{
if(reader == null)
return false;
reader.Read();
var quantDB = reader.GetInt32(1);
// Verifica se a quantidade do produto no banco de dados é >= que a quantidade do item na lista
if (quantDB >= quantItem)
return false;
else
return true;
}
}
}
Upvotes: 2