domingo, 20 de abril de 2014

[c# y Mysql] Mandar un arreglo de numeros a un procedimiento almacenado


Hoy tengo un problema que no habia podido resolver, aunque la verdad me cuesta mucho trabajo manejar un objeto persistente a la base de datos las transacciones en red regularmente son un poco lentos en C#(cosa que no me ocurre con JAVA). Por lo que el problema que tengo hoy es meter una serie de folios a la base de datos pero no quiero mandar una sentencia por cada folio porque como mi servidor esta en un maquina diferente dentro de una red, mandare el conjunto de folios dentro de un arreglo y lo procesare a traves de un procedimiento almacenado por lo que les comento el ejemplo completo. Primero creare una clase que me permitira generar una secuencia de folios para no tener problema, creare un windows form y hare un formulario como el siguiente:



 Primero validaremos que los dos primeros solo acepten digitos por lo que los amarramos a un mismo evento de tipo keypress. En este caso se llama isDigit aunque no regresara algo pues nos servira para evitar que se de eco en el cuadro de texto. 

private void isDigit(object sender, KeyPressEventArgs e)
        {
            if (!Char.IsDigit(e.KeyChar))
                e.KeyChar = '\0';
        }

Para el comision como solo necesito que valide que acepte numerico solo le puse una mascara de tipo currency. 

Ahora lo que necesitaremos en programar el boton de la palomita en este caso vamos a formatear la entrada que necesitamos y posteriormente se instanciara una clase que tendra la llama al procedimiento almacenado, el codigo es el siguiente: 

 private void agregaFolios(object sender, EventArgs e)
        {
            //convertimos lo que tiene el cuadro de texto a enteros
            int inicial = Convert.ToInt32(txtinicial.Text);
            int final = Convert.ToInt32(txtfinal.Text);
            //verificamos que folios tengan una secuencia 
            if( inicial <= final)
            {
                //cadena que tendra todos los numeros separados con ,
                string folios=""; 
                //ciclo que permite recorrer los valores y ponerlos en una cadena 
                for (int i = inicial; i <= final; i++)
                {
                    folios += i;
                    folios += ","; // no se preocupen porque termine con comas el procedimiento lo resolvera
                }
                //las validaciones basicas se cumplieron 
                // ahora haremos el procedimiento del registro por lo que pondre que el formulario me regrese OK para validacion posterior
                this.DialogResult = DialogResult.OK; 
                // Ahora instanciamos la clase que necesito 
                OpeAgentes soliciudes = new OpeAgentes();
                // mandamos los datos en este caso solo necesitan folios y los datos que quieran mandar.
                soliciudes.Addsolicitudes(folios, idagente, frmPanel.userActive.Iduser,Convert.ToDouble(textEdit1.Text));
                //cerramos el formulario
                this.Dispose(); 
                this.Close(); 
            }
            else
                MessageBox.Show("El folio inicial debe de ser menor que el final");
        }
Ahora abrimos la clase OpeAgentes y haremos el metodo Addsolicitudes para habilitar el insert. 

 public void Addsolicitudes(string folios, int idagente, int user, double comision)
        {
            MySqlConnection SQLConexion = default(MySqlConnection);            
            try
            {
                //creamos la conexion con la cadena
                SQLConexion = new MySqlConnection(SQLmConnStr);
                SQLConexion.Open(); //abrimos la conexion
                //mandamos llamar el procedimiento
                MySqlCommand SQLComando = new MySqlCommand("addfoliossolicitudes", SQLConexion);
                SQLComando.CommandType = CommandType.StoredProcedure;
                //agregamos los parametros que necesitara el procedimiento
                SQLComando.Parameters.AddWithValue("arrayFolio", folios);
                SQLComando.Parameters.AddWithValue("pagente", idagente);
                SQLComando.Parameters.AddWithValue("pcomision", comision);                
                SQLComando.Parameters.AddWithValue("piduser", user);

                //--- Ejecutar SQL
                SQLComando.ExecuteNonQuery();
                SQLComando.Dispose();
                SQLConexion.Close();
                SQLConexion.Dispose();
            }
            catch (MySqlException ex)
            {
                Console.Write(ex);

                if (SQLConexion.State == ConnectionState.Open)
                {
                    SQLConexion.Close();
                    SQLConexion.Dispose();
                }
            }
            finally
            {
                if (SQLConexion.State == ConnectionState.Open)
                {
                    SQLConexion.Close();
                    SQLConexion.Dispose();
                }

            }
        }

Ya por ultimo realizamos nuestro procedimiento almacenado para esto utilizaremos los siguiente

CREATE DEFINER=`root`@`localhost` PROCEDURE `addfoliossolicitudes`(arrayFolio text, pagente int, pcomision double, piduser int)
BEGIN
WHILE (LOCATE(',', arrayFolio) > 0)
DO
SET @value = ELT(1, arrayFolio);
    SET @FOLIO = SUBSTRING(arrayFolio, 1, LOCATE(',',arrayFolio)-1);
    SET arrayFolio = SUBSTRING(arrayFolio, LOCATE(',', arrayFolio) + 1);
    -- Se le pone IGNORE para si ya hay un folio solo ignore el error y siga con los demas folios
    -- INSERT QUE SE REPITE por cada folio que tenga
    INSERT IGNORE INTO `solicitudes`(x,y,z,w,u,v,j) 
                        VALUES(@FOLIO,pagente,pcomision,0,piduser,now(),'Algo');
END WHILE;
END

Y listo en este caso di de alta del 100 al 150 y el resultado es: 


Espero les pueda servir