有人可以给我一些与发布资源(内存资源)相关的提示吗?我只是一名学生而且我正在为一个假想的小市场建立一个系统,并且在测试将新产品添加到购物车的选项时,我发现 - 使用任务管理器 - 某些东西正在占用资源,因为调试期间程序使用的内存在每次单击特定按钮后都会增加几个字节。
我想知道我做错了什么,我还使用dispose来释放用于连接数据库的资源。请帮助我,你不必为我编码任何东西,只要解释一下我应该发布什么。
我上面提到的按钮是buttonAdicionar
事件所在的buttonAdicionar_Click
。
以下是pastebin的代码,如果你可以看看: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;
}
}
}
感谢。
答案 0 :(得分:2)
我最好的猜测是开始使用C#中的using
标签
而不是
myConnection = new connection(connectionString);
myConnection.open();
//do something with connection
myconnection.close();
你应该尝试:
using (connection myConnection = new connection(connectionstring))
{
//do something with myConnection
}
此外,使您的按钮不会直接调用DB注入代码,而是使用Control类。
例如
`private void buttonAdicionar_Click(object sender, EventArgs e)`
{
controlClass.DoSomethingNow()
}
并在您的控件类中使用以下方法:
controlClass :class
{
//make singleton?
public void DoSomethingNow()
{
using (connection myConnection = new connection(connectionstring))
{
//do something with myConnection
}
}
}
这样你就知道什么时候使用什么。您的IDE(如Visual Studio)可能会根据编译器的提示帮助您重新定位代码以获得更好的性能。
此外,作为一般提示,请尝试阅读设计模式。这些模式不仅限于C#,因此很高兴知道/必须在以后知道。
答案 1 :(得分:2)
你没有做任何本质上错误的事情,作为快速测试你可能想要在关闭/处理命令和连接时更改顺序。
da.Dispose();
dt.Dispose();
cmd.Dispose();
con.Close();
不确定这会解决您的问题,如果您按照其他地方的建议调整使用(),您将自动获得正确的订单。
我注意到的另一件事是你使用DataAdapter和DataTable但它们并没有真正添加任何值,这两个只是增加了不必要的内存开销,请尝试使用DataReader。使用()和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;
}
}
}