Problema al insertar datos en fomulario de windows form c# con sql

Estoy desarrollando un programa que estoy haciendo para mi clase, es un pequeño programa de una ferretería donde se guardan información de productos, clientes (con el fin de que si es distribuidor aplicar descuento), tipos de productos etcétera.

El problema se encuentra en la parte de facturación; algunas veces me permite guardar la factura y otras no, y no se que hacer, he probado todo lo que puedo saber, pero nada.

Este es mi código fuente:

protected override void Inicializar()
{
    base.Inicializar();

    // Llenamos el comboBox de Clientes
    CargarClientes();

    if (param_codigo == 0)
    {
        // Nuevo Registro
        NuevaFactura();
    }
    else
    {
        // Registro ya Existente
        btnAdicionarProducto.Enabled = false;

        VerFactura();
    }
}

private void CargarClientes()
{
    DataTable dt = null;
    string cadena_sql = "";
    cadena_sql = @"SELECT codigo, nombre_cliente 
                   FROM Clientes ";

    if (global.conn.SQLSelectDataTable(cadena_sql, ref dt))
    {
        cmbCodigoCliente.DataSource = dt;
    }
}

private void NuevaFactura()
{
    string cadena_sql = "";
    DataRow dr = null;
    int numero_factura = 0;

    cadena_sql = @"SELECT ISNULL(max(numero_factura),0) as maximo
                   FROM Facturas";

    if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
    {
        numero_factura = Convert.ToInt32(dr["maximo"]);
        numero_factura = numero_factura + 1;
        txtNumeroFactura.Text = numero_factura.ToString();
    }
}

private void VerFactura()
{
    VerEncabezado();
    VerDetalle();
}

private void VerEncabezado()
{
    DataRow dr = null;
    string cadena_sql = "";

    cadena_sql = @"SELECT * 
                   FROM Facturas
                   WHERE codigo = {0}";

    cadena_sql = string.Format(cadena_sql, param_codigo);

    if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
    {
        txtCodigo.Text = dr["codigo"].ToString();
        txtNumeroFactura.Text = dr["numero_factura"].ToString();
        dtpFecha.Value = Convert.ToDateTime(dr["fecha"]);
        cmbCodigoCliente.SelectedValue = Convert.ToInt32(dr["codigo_cliente"]);

        txtSubtotal.Text = Convert.ToDouble(dr["subtotal"]).ToString("###,###.00");
        txtImpuesto.Text = Convert.ToDouble(dr["impuesto"]).ToString("###,###.00");
        txtTotal.Text = Convert.ToDouble(dr["total"]).ToString("###,###.00");
    }
}

private void VerDetalle()
{
    string cadena_sql = "";
    DataTable dt = null;

    cadena_sql = @"SELECT 
                    fd.numero_linea
                    ,fd.codigo_producto
                    ,p.nombre as nombre_producto
                    ,fd.cantidad
                    ,fd.precio
                    ,(fd.cantidad * fd.precio) as total_item
                    FROM
                    FacturasDetalle fd
                    join
                    Productos p
                    on
                    fd.codigo_producto = p.codigo
                    WHERE
                    fd.codigo_factura = {0}
                    ";

    cadena_sql = string.Format(cadena_sql, param_codigo);

    if (global.conn.SQLSelectDataTable(cadena_sql, ref dt))
    {
        dgvDetalle.DataSource = dt;
    }
}

private void Totales()
{
    // Objetivo:
    // Recorrer el detalle, calcular total item
    // Sumarizar Subtotal, impuesto y total

    double cantidad = 0;
    double precio = 0;
    double total_item = 0;

    double subtotal = 0;
    double impuesto = 0;
    double total = 0;

    foreach (DataGridViewRow r in dgvDetalle.Rows)
    {
        cantidad = Convert.ToDouble(r.Cells["nCantidad"].Value);
        precio = Convert.ToDouble(r.Cells["nPrecio"].Value);
        total_item = cantidad * precio;
        r.Cells["nTotalItem"].Value = total_item;
        subtotal = subtotal + total_item;
    }

    // Calculamos impuesto y total
    impuesto = subtotal * 0.15;

    total = subtotal + impuesto;

    txtSubtotal.Text = subtotal.ToString("###,###.00");
    txtImpuesto.Text = impuesto.ToString("###,###.00");
    txtTotal.Text = total.ToString("###,###.00");
}


private void AdicionarProducto()
{
    try
    {
        int codigo_producto = 0;
        int indice_nuevo = 0;
        int numero_fila = 0;
        string nombre_producto = "";
        double precio_producto = 0;
        string cadena_sql = "";
        DataRow dr = null;                
        frmProductos prods = new frmProductos();
        prods.modo_actual = frmLista.ModoApertura.Busqueda;
        prods.ShowDialog(this);
        codigo_producto = prods.codigo_seleccionado;

        if (codigo_producto > 0)
        {
            // Agregamos una fila
            cadena_sql = @"SELECT nombre, precio
                            FROM productos 
                            WHERE codigo = {0}";
            cadena_sql = string.Format(cadena_sql, codigo_producto);

            if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
            {
                nombre_producto = dr["nombre"].ToString();
                precio_producto = Convert.ToDouble(dr["precio"]);
                indice_nuevo = dgvDetalle.Rows.Add();
                dgvDetalle.Rows[indice_nuevo].Cells["nNumeroLinea"].Value = indice_nuevo + 1;
                dgvDetalle.Rows[indice_nuevo].Cells["nCodigoProducto"].Value = codigo_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["sNombreProducto"].Value = nombre_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["nCantidad"].Value = 1;
                dgvDetalle.Rows[indice_nuevo].Cells["nPrecio"].Value = precio_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["nTotalItem"].Value = precio_producto;

                // Llamamos a la funcion de Totales
                Totales();
            }
        }
    }
    catch (Exception ex)
    {
    }
}

private void btnAdicionarProducto_Click(object sender, EventArgs e)
{
    AdicionarProducto();
}

private void dgvDetalle_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    Totales();
}

private void frmFactura_Load(object sender, EventArgs e)
{

}

protected override void AccionGuardar()
{
    if (param_codigo > 0)
    {
        MessageBox.Show("Factura no se puede editar");
        return;
    }

    if (GuardarEncabezado())
    {
        GuardarDetalle();
    }
}

private bool GuardarEncabezado()
{
    try
    {
        DataRow dr = null;
        int codigo = 0;
        string cadena_sql = "";

        cadena_sql = @"INSERT INTO [dbo].[Facturas]
                   ([numero_factura],
                   [codigo_cliente],
                   [fecha],
                   [subtotal],
                   [impuesto],
                   [total])
             VALUES
                   (
                    {0},
                    {1},
                    '{2}',
                    {3},
                    {4},
                    {5})";


        cadena_sql = string.Format(
                    cadena_sql,
                    txtNumeroFactura.Text,
                    cmbCodigoCliente.SelectedValue,
                    dtpFecha.Value.ToString("yyyyMMdd"),
                    Convert.ToDouble(txtSubtotal.Text),
                    Convert.ToDouble(txtImpuesto.Text),
                    Convert.ToDouble(txtTotal.Text)
                    );

        if (global.conn.SqlExec(cadena_sql))
        {
            cadena_sql = @"SELECT MAX(codigo) as maximo
                           FROM Facturas";

            if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
            {
                codigo = Convert.ToInt32(dr["maximo"]);
                txtCodigo.Text = codigo.ToString();
                return true;
            }
        }
        else
        {
            MessageBox.Show("Error al guardar encabezado: " + global.conn.SQLError() );
        }


    }
    catch (Exception ex)
    {

    }

    return false;
}

private void GuardarDetalle()
{
    try
    {
        int codigo_factura = 0;
        string cadena_base = "";
        string cadena_sql = "";

        codigo_factura = Convert.ToInt32(txtCodigo.Text);

        cadena_base = @"INSERT INTO 
                        FacturasDetalle
                       (codigo_factura
                       ,numero_linea
                       ,codigo_producto
                       ,cantidad
                       ,precio)
                 VALUES
                       (
                        {0}
                        ,{1}
                        ,{2}
                        ,{3}
                        ,{4}
                        )";

        foreach(DataGridViewRow r in dgvDetalle.Rows)
        {
            cadena_sql = string.Format(cadena_base
                      , codigo_factura
                      , Convert.ToInt32(r.Cells["nNumeroLinea"].Value)
                      , Convert.ToInt32(r.Cells["nCodigoProducto"].Value)
                      , Convert.ToDouble(r.Cells["nCantidad"].Value)
                      , Convert.ToDouble(r.Cells["nPrecio"].Value)
                      );

            if (! (global.conn.SqlExec(cadena_sql)) )
            {
                MessageBox.Show("Error al guardar detalle: " + global.conn.SQLError());
            }
        }

        MessageBox.Show("Factura Guardada con Exito");
        this.Close();
    }
    catch (Exception ex)
    {
    }
}

Y el error es el siguiente:

Captura de pantalla del error

0
задан 26.08.2016, 17:51
2 ответа

Позволь мне угадывать. Когда ты вводишь количество без десятичных, он не дает тебе ошибку... Использовав String. Format (...) ты заменяешь {i}, из-за которого ты имеешь в textbox. Восходите расскажи, что в textbox ты вводишь "30,30". Это тебе строит цепь с большим количеством стоимости, чем выраженные в статье Insert. А именно, '30' он это берет как стоимость и '30' как отличный другой, так как они отделены запятыми. Convert. ToDouble () не решает это тебе, потому что он конвертирует это тебе с форматом назначенной по умолчанию культуры. Использовав ее',' (что является культурой, которую ты считаешь установленной по умолчанию) он вновь ее тебе, помещает в',' когда ты делаешь String. Format () даже используя '.' в твоем textbox или замени ее методом повторно нравься () перед тем, как делать Convert.

(Изданное) решение: Используй неизменную культуру для превращения в string. Format:

cadena_sql = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                    cadena_sql,
                    txtNumeroFactura.Text,
                    cmbCodigoCliente.SelectedValue,
                    dtpFecha.Value.ToString("yyyyMMdd"),
                    Convert.ToDouble(txtSubtotal.Text),
                    Convert.ToDouble(txtImpuesto.Text),
                    Convert.ToDouble(txtTotal.Text)
                    );

Хорошее решение состояло бы в том, чтобы использовать параметры в консультации и кроме того ты предотвратил бы атаки SQL Injection. Но как ты говоришь, что ты изучаешь, можешь тестировать это присваивание, которое я предложил тебе.

Приветствие

1
ответ дан 24.11.2019, 13:33

Ошибка показывает, что количество колонн, объявленных в инструкции INSERT они меньше в количество стоимости, определенной в статье VALUES.

Проверь хорошо инструкции INSERT который ты используешь.

0
ответ дан 24.11.2019, 13:33