none
Classe geral para CRUD RRS feed

  • Pergunta

  • Olá pessoas,

    Sou iniciante em orientação a objetos e ao procurar sobre essa possibilidade não encontrei algo que me fosse claro.

    Meu problema é um seguinte, estou desenvolvendo uma aplicação C# de controle simples, com 11 tabelas, e quero criar uma classe só para fazer todos os Inserts / Updates / Deletes / Selects (carregando em textboxes/datetimepickers etc) passando por exemplo parametros do nome da tabela, campos, condição(where).

    Até hoje tenho feito uma classe CRUD para cada objeto(tabela) como a abaixo:

    using System;
    using System.Data.SqlClient;
    using System.Windows.Forms;
    
    namespace MotoTaxiControl.Classes.CRUD
    {
        class CRUDVeiculo
        {
            Banco banco = new Banco();
    
            private string sql = "";
    
            public void Inserir(Veiculo veiculo)
            {
                try
                {
                    sql = "INSERT INTO Veiculos " +
                          "(placa, " +
                          "renavam, " +
                          "fabricante, " +
                          "modelo, " +
                          "ano, " +
                          "cor, " +
                          "tipo_combustivel, " +
                          "licenciado_para, " +
                          "ultima_modificacao) " +
                          "VALUES " +
                          "(@placa, " +
                          "@renavam, " +
                          "@fabricante, " +
                          "@modelo, " +
                          "@ano, " +
                          "@cor, " +
                          "@tipo_combustivel, " +
                          "@licenciado_para, " +
                          "@ultima_modificacao)";
    
                    banco.Comando = new SqlCommand(sql, banco.Conexao);
    
                    banco.Comando.Parameters.AddWithValue("@placa", veiculo.Placa);
                    banco.Comando.Parameters.AddWithValue("@renavam", veiculo.Renavam);
                    banco.Comando.Parameters.AddWithValue("@fabricante", veiculo.Fabricante);
                    banco.Comando.Parameters.AddWithValue("@modelo", veiculo.Modelo);
                    banco.Comando.Parameters.AddWithValue("@ano", veiculo.Ano);
                    banco.Comando.Parameters.AddWithValue("@cor", veiculo.Cor);
                    banco.Comando.Parameters.AddWithValue("@tipo_combustivel", veiculo.Tipo_combustivel);
                    banco.Comando.Parameters.AddWithValue("@licenciado_para", veiculo.Licenciado_para);
                    banco.Comando.Parameters.AddWithValue("@ultima_modificacao", DateTime.Now);
    
                    banco.Conectar();
    
                    banco.Comando.ExecuteNonQuery();
    
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, "Erro ao executar inserir dados", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    banco.Desconectar();
                }
            }
    
            public void Editar(Veiculo veiculo, string placa)
            {
                try
                {
                    sql = "UPDATE Usuarios" +
                          "SET " +
                          "placa = @placa, " +
                          "renavam = @renavam, " +
                          "fabricante = @fabricante, " +
                          "modelo = @modelo, " +
                          "ano = @ano" +
                          "cor = @cor" +
                          "tipo_combustivel = @tipo_combustivel" +
                          "licenciado_para = @licenciado_para" +
                          "ultima_modificacao = @ultima_modificacao" +
                          "WHERE placa = @plc";
    
                    banco.Comando = new SqlCommand(sql, banco.Conexao);
    
                    banco.Comando.Parameters.AddWithValue("@placa", veiculo.Placa);
                    banco.Comando.Parameters.AddWithValue("@renavam", veiculo.Renavam);
                    banco.Comando.Parameters.AddWithValue("@fabricante", veiculo.Fabricante);
                    banco.Comando.Parameters.AddWithValue("@modelo", veiculo.Modelo);
                    banco.Comando.Parameters.AddWithValue("@ano", veiculo.Ano);
                    banco.Comando.Parameters.AddWithValue("@cor", veiculo.Cor);
                    banco.Comando.Parameters.AddWithValue("@tipo_combustivel", veiculo.Tipo_combustivel);
                    banco.Comando.Parameters.AddWithValue("@licenciado_para", veiculo.Licenciado_para);
                    banco.Comando.Parameters.AddWithValue("@ultima_modificacao", DateTime.Now);
    
                    banco.Conectar();
    
                    if (MessageBox.Show("Deseja realmente editar o registro de placa " + placa + " ?", "Confirmação de edição", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        banco.Comando.ExecuteNonQuery();
                    }
                    else
                    {
                        MessageBox.Show("Operação cancelada", "Informação do sistema", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, "Erro editar dados", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    banco.Desconectar();
                }
            }
    
            public void Retornar(string placa, Control[] controles, DateTimePicker licenciamento)
            {
                try
                {
                    sql = "SELECT * FROM Veiculos WHERE placa = @placa";
                    banco.Comando = new SqlCommand(sql, banco.Conexao);
                    banco.Comando.Parameters.AddWithValue("@placa", placa);
    
                    banco.Conectar();
    
                    banco.DataReader = banco.Comando.ExecuteReader();
    
                    while (banco.DataReader.Read())
                    {
                        controles[0].Text = banco.DataReader["placa"].ToString();
                        controles[1].Text = banco.DataReader["renavam"].ToString();
                        controles[2].Text = banco.DataReader["fabricante"].ToString();
                        controles[3].Text = banco.DataReader["modelo"].ToString();
                        controles[4].Text = banco.DataReader["ano"].ToString();
                        controles[5].Text = banco.DataReader["cor"].ToString();
                        controles[6].Text = banco.DataReader["tipo_combustivel"].ToString();
                        licenciamento.Value = Convert.ToDateTime(banco.DataReader["licenciado_para"].ToString());
                    }
    
                    banco.DataReader.Close();
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, "Erro ao coletar informação", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    banco.Desconectar();
                }
            }
    
            public void Deletar(string placa)
            {
                try
                {
                    sql = "DELETE FROM Veiculos WHERE placa = @placa";
    
                    banco.Comando = new SqlCommand(sql, banco.Conexao);
                    banco.Comando.Parameters.AddWithValue("@user", placa);
    
                    banco.Conectar();
                    if (MessageBox.Show("Deseja realmente deletar o veículo de placa " + placa + " ?", "Confirmação de exclusão", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        banco.Comando.ExecuteNonQuery();
                    }
                    else
                    {
                        MessageBox.Show("Operação cancelada", "Informação do sistema", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
    
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, "Erro ao executar comando", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    banco.Desconectar();
                }
            }
    
            public void PreencherLista(ListView listview)
            {
                try
                {
                    sql = "SELECT " +
                          "placa, modelo " +
                          "FROM Usuarios";
    
                    listview.Items.Clear();
                    banco.DataTable.Clear();
                    banco.Conectar();
                    banco.Comando = new SqlCommand(sql, banco.Conexao);
                    banco.DataAdapter = new SqlDataAdapter(banco.Comando);
                    banco.DataAdapter.Fill(banco.DataTable);
    
    
                    for (int i = 0; i < banco.DataTable.Rows.Count; i++)
                    {
                        ListViewItem item;
    
                        item = new ListViewItem(banco.DataTable.Rows[i]["placa"].ToString());
    
                        item.SubItems.Add(banco.DataTable.Rows[i]["modelo"].ToString());
    
                        listview.Items.Add(item);
                    }
                }
                catch (SqlException ex)
                {
                    MessageBox.Show(ex.Message, "Erro ao preencher lista", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    banco.Desconectar();
                }
            }
        }
    }
    

    Gostaria de saber um jeito de otimizar isso, economizar código, pois sinto que estou fazendo o contrário tendo que criar um para cada das 11 tabelas.

    Grato desde já por qualquer ajuda!


    quinta-feira, 22 de novembro de 2018 14:02

Respostas

  • Bom dia Diego como vai?

    segue os trechos comentados, veja se esclarece a ideia.

    Qualquer duvida estou a disposição

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Produto
    	{
    		public int OID { get; set; }
    
    		public string Descricao { get; set; }
    
    		public int teste { get; set; }
    
    		public decimal valor { get; set; }
    	}
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			// Instancio a classe produto
    			var prod = new Produto { OID = 1, Descricao = "Teste" };
    
    			//Instancio a classe crud tipando ela como Produto, ou seja estou dizendo a ela que o "T" é produto
    			var crud = new Crud<Produto>();
    
    			//Chamo o metodo inserir que espera um objeto do tipo "T", que no caso é do tipo produto, passo o objeto produto (prod) e o nome da tabela
    			crud.Inserir(prod, "Produto");
    
    
    		}
    	}
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Crud<T> where T : new() // quando deixamos a classe generica, ela não sabe qual o objeto que vc vai informar para usar-la, o T pode
    								  // produto, como pode ser qualquer outro objeto que vc tenha.
    	{
    		// aqui o metodo espera um objeto qualquer do tipo T, que no nosso caso é do tipo Produto, e o nome da tabela.
    		public void Inserir(T objeto, string tabelaNome)
    		{
    			// nessa linha, pegamos todas as propiedade do objeto, no caso do produto, esta sendo pego a o atributo OID, Descricao, teste e valor
    			// o metodo GetProperties() retorna um array com os nomes das propiedades do nosso objeto (Produto)
    			var propiedades = objeto.GetType().GetProperties();
    
    			//Aqui começamos a construir no query sql
    			string sql = string.Format("INSERT INTO {0} ", tabelaNome);	
    			//Percorremos cada item que esta em propiedade com  o for
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				//estamos adicionando na string sql o nome da nossa propiedade, que esta contida no array propiedades, com o Name
    				sql += propiedades[i].Name;
    				// esse if serve apenas para ver se não é a ultima propiedade para irmos adicionando as virgulas
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				// caso seja a ultima propiedade colocamos o VALUES (, no momento a string sql esta assim: "INSERT INTO PRODUTO OID, Descricao, teste, valor VALUES ("
    				else
    					sql += " VALUES (";
    			}	
    			// fazenos outro for para percorrer o array propiedades, da primeira vez pegamos o nome da propiedade agora vamos pegar o valor contido nelas
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				// aqui pegamos o valor que esta contido na propiedade, exemplo OID = 1, Descricao = "teste", etc.
    				sql += propiedades[i].GetValue(objeto);
    				// adicionando as virgulas
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				// fechando a query, exemplo : "INSERT INTO PRODUTO OID, Descricao, teste, valor VALUES (1, teste, 10, 4.00)"
    				else
    					sql += ")";
    			}
    			
    		}
    	}
    }


    • Editado Paulo Felipe Leite segunda-feira, 26 de novembro de 2018 11:40
    • Marcado como Resposta Diego Devesa terça-feira, 27 de novembro de 2018 01:35
    segunda-feira, 26 de novembro de 2018 11:40

Todas as Respostas

  • Óla Diego,

    Pesquise mais sobre Entity Framework ele é um framework que cuida da parte de banco de dados, vai deixar seu código muito mais enxuto.

    http://www.entityframeworktutorial.net/code-first/what-is-code-first.aspx


    quinta-feira, 22 de novembro de 2018 14:16
  • Boa tarde!

    Agradeço a sugestão, porém, preciso de algo que me permita aprender sem utilização de frameworks, pois me ajudaria a desenvolver a lógica em questão.

    quinta-feira, 22 de novembro de 2018 15:05
  • Boa tarde!

    Entendi, bom nesse caso, sugiro estudar generics.

    https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/generics/

    quinta-feira, 22 de novembro de 2018 15:58
  • Você por acaso teria algum exemplo prático? Só ter a documentação não ajuda muito, não mostra nada aplicado ao crud
    quinta-feira, 22 de novembro de 2018 17:27
  • Boa tarde Diego, fiz um exemplo básico aqui, da pra você aprender o conceito e adaptar e/ou ajustar.

    fiz somente a montagem da query sql, com isso vc consegue aplicar para o restante. Qualquer dúvida estou disponivel.

    class Program
    	{
    		static void Main(string[] args)
    		{
    			var prod = new Produto { OID = 1, Descricao = "Teste" };
    			var crud = new Crud<Produto>();
    			crud.Inserir(prod, "Produto");
    		}
    	}

    class Produto
    	{
    		public int OID { get; set; }
    
    		public string Descricao { get; set; }
    	}

    class Crud<T> where T : new()
    	{
    		public void Inserir(T objeto, string tabelaNome)
    		{
    			var propiedades = objeto.GetType().GetProperties();
    			string sql = string.Format("INSERT INTO {0} ", tabelaNome);			
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				sql += propiedades[i].Name;
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				else
    					sql += " VALUES (";
    			}			
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				sql += propiedades[i].GetValue(objeto);
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				else
    					sql += ")";
    			}
    			
    		}
    	}

    quinta-feira, 22 de novembro de 2018 18:55
  • Fiquei um pouco perdido, poderia comentar o código?
    sábado, 24 de novembro de 2018 16:56
  • Bom dia Diego como vai?

    segue os trechos comentados, veja se esclarece a ideia.

    Qualquer duvida estou a disposição

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Produto
    	{
    		public int OID { get; set; }
    
    		public string Descricao { get; set; }
    
    		public int teste { get; set; }
    
    		public decimal valor { get; set; }
    	}
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			// Instancio a classe produto
    			var prod = new Produto { OID = 1, Descricao = "Teste" };
    
    			//Instancio a classe crud tipando ela como Produto, ou seja estou dizendo a ela que o "T" é produto
    			var crud = new Crud<Produto>();
    
    			//Chamo o metodo inserir que espera um objeto do tipo "T", que no caso é do tipo produto, passo o objeto produto (prod) e o nome da tabela
    			crud.Inserir(prod, "Produto");
    
    
    		}
    	}
    }

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp2
    {
    	class Crud<T> where T : new() // quando deixamos a classe generica, ela não sabe qual o objeto que vc vai informar para usar-la, o T pode
    								  // produto, como pode ser qualquer outro objeto que vc tenha.
    	{
    		// aqui o metodo espera um objeto qualquer do tipo T, que no nosso caso é do tipo Produto, e o nome da tabela.
    		public void Inserir(T objeto, string tabelaNome)
    		{
    			// nessa linha, pegamos todas as propiedade do objeto, no caso do produto, esta sendo pego a o atributo OID, Descricao, teste e valor
    			// o metodo GetProperties() retorna um array com os nomes das propiedades do nosso objeto (Produto)
    			var propiedades = objeto.GetType().GetProperties();
    
    			//Aqui começamos a construir no query sql
    			string sql = string.Format("INSERT INTO {0} ", tabelaNome);	
    			//Percorremos cada item que esta em propiedade com  o for
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				//estamos adicionando na string sql o nome da nossa propiedade, que esta contida no array propiedades, com o Name
    				sql += propiedades[i].Name;
    				// esse if serve apenas para ver se não é a ultima propiedade para irmos adicionando as virgulas
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				// caso seja a ultima propiedade colocamos o VALUES (, no momento a string sql esta assim: "INSERT INTO PRODUTO OID, Descricao, teste, valor VALUES ("
    				else
    					sql += " VALUES (";
    			}	
    			// fazenos outro for para percorrer o array propiedades, da primeira vez pegamos o nome da propiedade agora vamos pegar o valor contido nelas
    			for (int i = 0; i < propiedades.Count(); i++)
    			{
    				// aqui pegamos o valor que esta contido na propiedade, exemplo OID = 1, Descricao = "teste", etc.
    				sql += propiedades[i].GetValue(objeto);
    				// adicionando as virgulas
    				if (i < propiedades.Count() - 1)
    					sql += ", ";
    				// fechando a query, exemplo : "INSERT INTO PRODUTO OID, Descricao, teste, valor VALUES (1, teste, 10, 4.00)"
    				else
    					sql += ")";
    			}
    			
    		}
    	}
    }


    • Editado Paulo Felipe Leite segunda-feira, 26 de novembro de 2018 11:40
    • Marcado como Resposta Diego Devesa terça-feira, 27 de novembro de 2018 01:35
    segunda-feira, 26 de novembro de 2018 11:40
  • Muito obrigado cara, entendi como funciona, vou tentar implementar algo parecido em minha próxima aplicação de estudo!

    Valeu mesmo, obrigado pela paciência!

    terça-feira, 27 de novembro de 2018 01:35