none
Erro SqlCommand.ExecuteNonQuery RRS feed

  • Pergunta

  • Boa noite,

    Não entendo porque o comando ExecuteNonQuery da classe SqlCommand esta me trazer o erro de:

    "Arithmetic overflow error converting numeric to data type numeric.
    The statement has been terminated."

    Vamos combinar que essa mensagem ta TOSCA!! É a mesma coisa que dizer que um copo não pode ser um copo!! Pqp!! ¬¬'

    Segue meu fonte:

    Classe que monta as querys e faz conexão com o banco:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Configuration;
    using System.Data.SqlClient;
    using System.Collections;
    
    namespace Testes.Classes.BancoDados
    {
        public enum TipoDadoBancoDados
        {
            String, DateTime, Numeric
        }
    
        public enum TipoConexao
        {
            SqlServer
        }
    
        public class Registro
        {
            private string nomeRegistro;
            public string NomeRegistro
            {
                get
                {
                    return nomeRegistro;
                }
            }
    
            public Registro(string registro)
            {
                nomeRegistro = registro;
            }
        }
    
        public class RegistroValor
        {
            private string nomeRegistro;
            private TipoDadoBancoDados tipoRegistro;
            private object valorRegistro = new object();
            public string NomeRegistro
            {
                get
                {
                    return nomeRegistro;
                }
            }
    
            public DbType TipoRegistro
            {
                get
                {
                    switch (tipoRegistro)
                    {
                        case TipoDadoBancoDados.DateTime:
                            return DbType.DateTime;
                        case TipoDadoBancoDados.String:
                            return DbType.String;
                        case TipoDadoBancoDados.Numeric:
                            return DbType.Double;
                        default:
                            throw new ArgumentException("TipoDado não informado.");
                    }
                }
            }
    
            public object ValorRegistro
            {
                get
                {
                    return valorRegistro;
                }
            }
    
            public RegistroValor(string registro, TipoDadoBancoDados tipo, object Pvalor)
            {
                nomeRegistro = registro;
                tipoRegistro = tipo;
                valorRegistro = Pvalor;
            }
        }
    
        public class WhereRegistro
        {
            private string nomeRegistro;
            private TipoDadoBancoDados tipoRedistro;
            private string compara;
            private object valorRegistro;
    
            public string NomeRegistro
            {
                get
                {
                    return nomeRegistro;
                }
            }
            public DbType TipoRegistro
            {
                get
                {
                    switch (tipoRedistro)
                    {
                        case TipoDadoBancoDados.DateTime:
                            return DbType.DateTime;
                        case TipoDadoBancoDados.String:
                            return DbType.String;
                        case TipoDadoBancoDados.Numeric:
                            return DbType.Double;
                        default:
                            throw new ArgumentException("TipoDado não informado.");
                    }
                }
            }
    
            public object ValorRegistro
            {
                get
                {
                    return valorRegistro;
                }
            }
    
            public string Compara
            {
                get
                {
                    return compara;
                }
            }
    
            public WhereRegistro(string PNomeRegistro, TipoDadoBancoDados PTipoRegistro, string PCompara, object PValor)
            {
                nomeRegistro = PNomeRegistro;
                tipoRedistro = PTipoRegistro;
                compara = PCompara;
                valorRegistro = PValor;
            }
        }
    
    
        public class ConexaoBancoDados : IDisposable
        {
            private List<string> tabela;
            private SqlConnection conexaoBanco;
            private SqlCommand comando;
            private ArrayList registros;
    
            public ConexaoBancoDados(TipoConexao conexao)
            {
                switch (conexao)
                {
                    case TipoConexao.SqlServer:
                        conexaoBanco = new SqlConnection(ConfigurationManager.AppSettings["ConnectionStringSqlServer"].ToString());
                        comando = conexaoBanco.CreateCommand();
                        registros = new ArrayList();
                        break;
                }
            }
    
            public int TempoComando
            {
                get
                {
                    return comando.CommandTimeout;
                }
                set
                {
                    comando.CommandTimeout = value;
                }
            }
    
            public void IniciarTransacao()
            {
                comando.Transaction.Connection.BeginTransaction();
            }
    
            public void ComitTransacao()
            {
                comando.Transaction.Commit();
            }
    
            public void RollBackTransacao()
            {
                comando.Transaction.Rollback();
            }
    
            public void AdicionarRegistro(string PNomeRegistro)
            {
                registros.Add(new Registro(PNomeRegistro));
            }
    
            public void AdicionarRegistro(string PNomeRegistro, TipoDadoBancoDados PTipoRegistro, object PValorRegistro)
            {
                try
                {
                    switch (PTipoRegistro)
                    {
                        case TipoDadoBancoDados.DateTime:
                            registros.Add(new RegistroValor(PNomeRegistro, PTipoRegistro, DateTime.Parse(PValorRegistro.ToString())));
                            break;
                        case TipoDadoBancoDados.Numeric:
                            registros.Add(new RegistroValor(PNomeRegistro, PTipoRegistro, decimal.Parse(PValorRegistro.ToString())));
                            break;
                        case TipoDadoBancoDados.String:
                            registros.Add(new RegistroValor(PNomeRegistro, PTipoRegistro, PValorRegistro.ToString()));
                            break;
                    }
                }
                catch (FormatException)
                {
                    this.Dispose();
                    throw new FormatException("Tipo de dado inválido para o valor informado.");
                }
                catch (OverflowException)
                {
                    this.Dispose();
                    throw new OverflowException("Tipo de dado inválido para o valor informado.");
                }
                catch (Exception ex)
                {
                    this.Dispose();
                    throw new Exception("Erro AdicionaRegistro: " + ex.Message);
                }
            }
    
            public void AdicionaTabela(string nomeTabela)
            {
                tabela.Add(nomeTabela);
            }
    
            public void AdicionaWhere(string PNomeRegistro, string PCompara, TipoDadoBancoDados PTipoRegistro, object PValor)
            {
                try
                {
                    switch (PTipoRegistro)
                    {
                        case TipoDadoBancoDados.DateTime:
                            registros.Add(new WhereRegistro(PNomeRegistro, PTipoRegistro, PCompara, DateTime.Parse(PValor.ToString())));
                            break;
                        case TipoDadoBancoDados.Numeric:
                            registros.Add(new WhereRegistro(PNomeRegistro, PTipoRegistro, PCompara, decimal.Parse(PValor.ToString())));
                            break;
                        case TipoDadoBancoDados.String:
                            registros.Add(new WhereRegistro(PNomeRegistro, PTipoRegistro, PCompara, PValor.ToString()));
                            break;
                    }
                }
                catch (FormatException)
                {
                    this.Dispose();
                    throw new FormatException("Tipo de dado inválido para o valor informado.");
                }
                catch (OverflowException)
                {
                    this.Dispose();
                    throw new OverflowException("Tipo de dado inválido para o valor informado.");
                }
                catch (Exception ex)
                {
                    this.Dispose();
                    throw new Exception("Erro AdicionaRegistro: " + ex.Message);
                }
            }
    
            public void Inserir(string PTabela)
            {
                StringBuilder registrosSql = new StringBuilder();
                StringBuilder parametrosSql = new StringBuilder();
                
                bool primeiro = true;
                foreach (RegistroValor regValor in registros)
                {
                    if (primeiro)
                    {
                        registrosSql.AppendFormat("({0}", regValor.NomeRegistro);
                        parametrosSql.AppendFormat("(@{0}", regValor.NomeRegistro);
                        comando.Parameters.AddWithValue("@" + regValor.NomeRegistro, regValor.ValorRegistro);
                        //comando.Parameters["@" + regValor.NomeRegistro].DbType = regValor.TipoRegistro;
                        primeiro = false;
                    }
                    else
                    {
                        registrosSql.AppendFormat(", {0}", regValor.NomeRegistro);
                        parametrosSql.AppendFormat(", @{0}", regValor.NomeRegistro);
                        comando.Parameters.AddWithValue("@" + regValor.NomeRegistro, regValor.ValorRegistro);
                        //comando.Parameters["@" + regValor.NomeRegistro].DbType = regValor.TipoRegistro;
                    }
                }
                registrosSql.Append(")");
                parametrosSql.Append(")");
    
                comando.CommandText = String.Format("INSERT INTO {0} {1} VALUES {2}", PTabela, registrosSql, parametrosSql);
    
                try
                {
                    comando.Connection.Open();
                    comando.ExecuteNonQuery();
                    comando.Connection.Close();
                }
                catch (Exception ex)
                {
                    throw new Exception("Erro ao inserir: " + ex.Message);
                }
                finally
                {
                    this.Dispose();
                }
            }
    
            public void Dispose()
            {
                tabela.Clear();
                conexaoBanco.Close();
                conexaoBanco.Dispose();
                comando.Dispose();
                registros = new ArrayList();
            }
        }
    }

    Classe onde envio uns parametros para testar o metodo Inserir da classe acima:

    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 System.Configuration; using Testes.Classes.BancoDados; namespace Testes { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Shown(object sender, EventArgs e) { } private void button1_Click(object sender, EventArgs e) { try { ConexaoBancoDados conexao = new ConexaoBancoDados(TipoConexao.SqlServer); conexao.AdicionarRegistro("NRANOS", TipoDadoBancoDados.Numeric, 23); conexao.AdicionarRegistro("NOCLIENTE", TipoDadoBancoDados.String, "VAGNER NASCIMENTO"); conexao.AdicionarRegistro("DTNASCIMENTO", TipoDadoBancoDados.DateTime, DateTime.Now); conexao.AdicionarRegistro("CREDITOLIMITE", TipoDadoBancoDados.Numeric, 1598.58); conexao.Inserir("CLIENTE"); MessageBox.Show("Cliente Inserido com Sucesso!"); } catch (Exception ex) { MessageBox.Show("Erro ao tentar inserir: " + ex.Message); } } } }


    Scrip da minha tabela CLIENTE:

    CREATE TABLE [dbo].[CLIENTE](
    	[NRANOS] [numeric](8, 2) NULL,
    	[NOCLIENTE] [varchar](250) NULL,
    	[DTNASCIMENTO] [datetime] NULL,
    	[CREDITOLIMITE] [numeric](10, 9) NULL,
    	[PKCLIENTE] [int] IDENTITY(1,1) NOT NULL,
    PRIMARY KEY CLUSTERED 
    (
    	[PKCLIENTE] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    GO
    
    SET ANSI_PADDING OFF
    GO
    

    Já revisei, re-revisei, re-re-revisei e não consigo encontrar a fonte do erro.

    Alguém tem idéia do que pode esta ocorrendo?

    Grato desde já,

    Vagner

    sexta-feira, 20 de abril de 2012 00:35

Respostas

  • Boa tarde Andre.

    Sua dica não resolveu meu problema, porém me abriu os olhos para a solução.

    Fiz o que você disse e também alterei a coluna da tabela para Float ao invés de Numeric(10,9).

    Obrigado.

    • Marcado como Resposta VagnerNasc sábado, 28 de abril de 2012 16:16
    sábado, 28 de abril de 2012 16:16

Todas as Respostas

  • Alo, primeiro, voce nao deveria colocar o projecto todo aki. Deverias simplesmente colocar o codigo que gera o erro e o erro produzido.

    Agora, que vai analizar todo o codigo?

    A minha priemira pergunta e a seguinte, porque voce tem oteu insert desta form: 

    String.Format("INSERT INTO {0} {1} VALUES {2}?

    Nao seria mais facil fazer assim: insert into nomedatabela value(parametros)?


    Se o amor fosse pecado, quem seria INOCENTE?

    sexta-feira, 20 de abril de 2012 08:56
  • Alo, Segundo, voce tem uma onde o erro e gerado, em k linha?

    Acho que voce esta fazendo insert num campo da tabela que nao recebe este tipo de data. Veja a tua base de dados, veja que tipo de valors os campos recebem e qual e o tamanho de cada um.

    Voce esta a disparar informacao em campos que nao podem receber um tipo de informacao.


    Se o amor fosse pecado, quem seria INOCENTE?

    sexta-feira, 20 de abril de 2012 09:04
  • Terceiro e ultimo: Nao te aconselho a usar Irraylist().

    Use apenas List<>.


    Se o amor fosse pecado, quem seria INOCENTE?

    sexta-feira, 20 de abril de 2012 09:05
  • Boa noite caro Malange,

    Coloque todos os fontes que estou utilizando, inclusive o script da tabela, para caso alguém tenha interesse crie um projeto e apenas copie, criando inclusive a tabela que estou usando.

    Eu crio a query desta maneira para ser mais dinâmica, assim o desenvolvedor que utilizar a minha classe de bancos pode inserir valores conforme a necessidade, sem ter que se procupar com o erro de "Estão faltando campos da tabela em sua query". Fazendo desta maneira os campos que podem ser NULL não precisam ser informados e serão setados como NULL.

    O Format, neste caso, significa: INSET INTO NOMETABELA (COLUNA1, COLUNA2, COLUNA_ETC) VALUES (@Parametro1, @Parametro2, @Parametro_ETC).

    Entede? (Like Pele.. rsrs)

    terça-feira, 24 de abril de 2012 23:07
  • R: Se você copiar o primeiro fonte e colar em um arquivo .cs ou .txt(utilizando o NotePad++) vai aparecer o numero das linhas, e fica na linha número 300, onde tem o comand, que deveria executar o insert no meu banco de dados.

    comando.ExecuteNonQuery();

    Quanto a suspeita de estar enviando um valor que não cabe em algum campo da tabela creio que não seja.

    Veja as colunas da minha tabela:

    [NRANOS] [numeric](8, 2) NULL, [NOCLIENTE] [varchar](250) NULL, [DTNASCIMENTO] [datetime] NULL, [CREDITOLIMITE] [numeric](10, 9) NULL, [PKCLIENTE] [int] IDENTITY(1,1) NOT NULL,

    E esses são os valores que tento inserir:

     ConexaoBancoDados conexao = new ConexaoBancoDados(TipoConexao.SqlServer);
                    conexao.AdicionarRegistro("NRANOS", TipoDadoBancoDados.Numeric, 23);
                    conexao.AdicionarRegistro("NOCLIENTE", TipoDadoBancoDados.String, "VAGNER NASCIMENTO");
                    conexao.AdicionarRegistro("DTNASCIMENTO", TipoDadoBancoDados.DateTime, DateTime.Now);
                    conexao.AdicionarRegistro("CREDITOLIMITE", TipoDadoBancoDados.Numeric, 1598.58);
    
                    conexao.Inserir("CLIENTE");

    Observe:

    Valor:                                                 Campo Correspondente:

    23                                                       [NRANOS] [NUMERIC] (8,2) NULL

    VAGNER NASCIMENTO                        [NOCLIENTE] [VARCAHR] (250) NULL

    DateTime.Now(data e hora atual)      [DTNASCIMENTO] [DATETIME] NULL

    1598.58                                             [CREDITOLIMITE] [NUMERIC] (10,9) NULL

    O campo PKCLIENTE não precisa ser informado por ser do tipo INDENTITY, que é auto-incrementado e gerenciado pelo SQL Server.

    Pela mensagem pensei que podesse ser nos numerics (NRANOS e CREDITOLIMITE) mas ambos estão com um tamanho preparados para receber os dados que estou enviando.

    Grato.

    terça-feira, 24 de abril de 2012 23:26
  • A vantagem de utilizar um ArrayList neste caso é que eu posso enfiar em uma só linhas as classes que eu quiser. Veja, eu tenho calsse para armazenar as clausulas Where, Registro, Registro com valor etc... e eu posso inserir quantos objetos dela eu quiser em um ArrayList.

    Por exemplo, digamos que eu inserir 3 objetos REGISTRO, 2 WHERE e 1 REGISTRO COM VALOR, tudo em um único arraylist. Quando eu quiser recuperar estes valores basta eu abrir um foreach informando a classes que eu quero e o arraylist:

    Ex.: foreach(REGISTRO reg in MEUARRAYLIST){bla bla bla...}

    foreach(WHERE wher in MEUARRAYLIST){bla bla bla...}

    Entendeu?

    Agradeço a atenção desde já.

    terça-feira, 24 de abril de 2012 23:31
  • Vagner,

    Quando você detecta que é Numeric, tente fazer um double.Parse, ao invés de decimal.Parse...


    André Alves de Lima
    Microsoft MVP - Client App Dev
    Visite o meu site: http://www.andrealveslima.com.br
    Me siga no Twitter: @andrealveslima

    quarta-feira, 25 de abril de 2012 10:57
    Moderador
  • Esta linha explica tudo: "assim o desenvolvedor que utilizar a minha classe de bancos pode inserir valores conforme a necessidade"

    O erro persiste?


    Se o amor fosse pecado, quem seria INOCENTE?

    quarta-feira, 25 de abril de 2012 18:46
  • Boa tarde Andre.

    Sua dica não resolveu meu problema, porém me abriu os olhos para a solução.

    Fiz o que você disse e também alterei a coluna da tabela para Float ao invés de Numeric(10,9).

    Obrigado.

    • Marcado como Resposta VagnerNasc sábado, 28 de abril de 2012 16:16
    sábado, 28 de abril de 2012 16:16