none
Insertar registros en tabla Sql desde DataGridView y TextBox RRS feed

  • Pregunta

  • Saludos expertos, estoy trabajando un proyecto en C# 2012 con Sql Server 2012, estoy intentado agregar articulos de una factura a una tabla en sql server enviando los datos desde textbox y un DataGridView. El problema es que cuando el Grid tiene mas de un registro agrega la primera fila y cuando intenta con la segunda salta un error diciendo que la variable que corresponde al IdCliente ya se ha declarado y que los nombres de variables deben ser únicos dentro de un lote de consultas o procedimiento almacenado.

    en mi tabla ese campo no esta marcado como llave, osea que no necesariamente debe ser único. Y si inserto solo un registro a la vez con el mismo Id de cliente lo almacena sin dificultad. a continuación el código que he estado usando y apreciaría algunos consejos para solucionar esta dificultad. Agradezco de antemano su ayuda.

    public void CrearFactura()
            {
                sql = @"Insert Into Facturacion 
                            (IdCliente, FechaFactura,IdTipoFactura,
                       IdArticulo,PrecioVenta,Cantidad,Subtotal,
                            Impuestos,Descuento,TotalFacturado)
                        VALUES
                       (@IdCliente, @FechaFactura,@IdTipoFactura,
                       @IdArticulo,@PrecioVenta,@Cantidad,@Subtotal,
                       @Impuestos,@Descuento,@TotalFacturado)";

                using (SqlCommand cmd = new SqlCommand(sql, cnx))
                {
                    cnx.Open();

                    try
                        {
                    foreach (DataGridViewRow fila in dgvFactura.Rows)
                    {
                        cmd.Parameters.AddWithValue("@IdCliente", txtIdCliente.Text);
                        cmd.Parameters.AddWithValue("@FechaFactura", Convert.ToDateTime(lblFecha.Text));
                        if (rbContado.Checked == true)
                        {
                            cmd.Parameters.AddWithValue("@IdTipoFactura", Convert.ToInt32(1));
                        }
                        else if (rbCredito.Checked == true)
                        {
                            cmd.Parameters.AddWithValue("@IdTipoFactura", Convert.ToInt32(2));
                        }
                        cmd.Parameters.AddWithValue("@IdArticulo", fila.Cells["IdArticulo"].Value);
                        cmd.Parameters.AddWithValue("@PrecioVenta", fila.Cells["PrecioVenta"].Value);
                        cmd.Parameters.AddWithValue("@Cantidad", fila.Cells["Cantidad"].Value);
                        cmd.Parameters.AddWithValue("@Subtotal", lblSubTotal.Text);
                        cmd.Parameters.AddWithValue("@Impuestos", lblImpuestos.Text);
                        cmd.Parameters.AddWithValue("@Descuento", lblDescuento.Text);
                        cmd.Parameters.AddWithValue("@TotalFacturado", lblTotal.Text);
                                            
                        cmd.ExecuteNonQuery();
                        }
                        MessageBox.Show("Registro agregado.");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                    finally
                    {
                        cnx.Close();
                    }
                    
                }
            }

    domingo, 31 de enero de 2016 5:47

Respuestas

  • Fíjate que a cada vuelta del bucle foreach vuelver a agregarle los parámetros al "cmd". Por eso a la segunda vuelta te indica que hay un duplicado en el primero que intenta procesar.

    La solución más sencilla (pero no la más eficiente) consiste en poner un cmd.Parameters.Clear() al principio del bucle (antes de añadir el primer parámetro).

    Si lo quieres más eficiente, saca la creación de parámetros fuera del bucle (en cuyo caso tendrás que usar el "Add" y no el "AddWithValue"), y dentro del bucle simplemente cámbiales el .Value a los parámetros. Esto es un poco más eficiente porque solo se crean una vez, en lugar de borrarlos y volverlos a crear a cada iteración. Además con el Add les podrás poner el tipo y la longitud correcta, con lo que evitarás polucionar la caché de procedimientos en el servidor, tal como ocurre con el AddWithValue.

    domingo, 31 de enero de 2016 8:18
    Moderador