Erro SqlCommand.ExecuteNonQuery
-
2012년 4월 20일 금요일 오전 12:35
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
- 이동됨 Caio Proiete [MVP]MVP, Moderator 2012년 4월 25일 수요일 오전 12:33 Movido para o forum apropriado (De:C#)
모든 응답
-
2012년 4월 20일 금요일 오전 8:56
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?
-
2012년 4월 20일 금요일 오전 9:04
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?
-
2012년 4월 20일 금요일 오전 9:05
Terceiro e ultimo: Nao te aconselho a usar Irraylist().
Use apenas List<>.
Se o amor fosse pecado, quem seria INOCENTE?
-
2012년 4월 24일 화요일 오후 11:07
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)
-
2012년 4월 24일 화요일 오후 11:26
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.
-
2012년 4월 24일 화요일 오후 11:31
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á.
-
2012년 4월 25일 수요일 오전 10:57중재자
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- 답변으로 제안됨 Fernando Henrique Inocêncio Borba FerreiraMVP, Moderator 2012년 4월 25일 수요일 오후 2:39
-
2012년 4월 25일 수요일 오후 6:46
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?
-
2012년 4월 28일 토요일 오후 4:16
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.
- 답변으로 표시됨 VagnerNasc 2012년 4월 28일 토요일 오후 4:16

