none
Porcedimiento almacenado que devuelve datos RRS feed

  • Pregunta

  • Amigos buenas tardes, tengo una tabla con  muchas columnas  , pero de esta solo necesito algunos  campos  cuando hago la selección , cree un strore procedure de selección y este lo cargo a un tableadapter en ado.net , pero cuando lanzo el evento este me desborda la app, hay alguna manera de que me pase  a los controles de asp.net los campo que eh llamado en el select , espero me puedan ayudar ,este es el código que tengo 

    create proc SeleccionarCliente
    @codclie varchar(50)
    as
    begin

    select Descrip,TipoID,Direc1,Direc2,Pais,Estado,Ciudad,Municipio,Telef,Movil,Email,CodVend,CodConv,Observa,EsCredito from SACLIE where CodClie ='24318655'
    end

    en C# lo llamo de esta manera

      DsRemision.SACLIEDataTable cliente = CADCliente.ConsultaCliente(txtDocClie.Text);
                foreach (DataRow row in cliente.Rows)
                {
                    txtDocClie.Text = row["CodClie"].ToString();
                    txtDesClie.Text = row["Descrip"].ToString();
                    drpTDCliente.SelectedValue = row["TipoID"].ToString();
                    txtDirClie1.Text = row["Direc1"].ToString();
                    txtDirClien2.Text = row["Direc2"].ToString();
                    drpPais.SelectedValue = row["Pais"].ToString();
                    drpEstado.SelectedValue = row["Estado"].ToString();
                    drpCiudad.SelectedValue = row["Ciudad"].ToString();
                    drpMunicipio.SelectedValue = row["Municipio"].ToString();
                    txtTelClie.Text = row["Telef"].ToString();
                    txtcelClie.Text = row["Movil"].ToString();
                    txtEmailClie.Text = row["Email"].ToString();
                    drpVendedor.SelectedValue = row["CodVend"].ToString();
                    drpConClie.SelectedValue = row["CodConv"].ToString();
                    TextareaClie.InnerText = row["Observa"].ToString();
                    credito = Convert.ToInt32(row["EsCredito"].ToString());
                    if (credito == 1) { chboxcredito.Checked = true;}
                    else { chboxcredito.Checked = false; }

                }

    lientScript.RegisterStartupScript(this.GetType(), "Mensaje", "<Script>swal" +
                  "('Cliente!', 'Consultado  con exito!', 'success')</Script>");


    Daniel

    lunes, 27 de enero de 2020 19:40

Respuestas

  • Hola Dannycv012:

    Estás seguro de que llamas al procedure?

    Cuantas rows te devuelve?


    lunes, 27 de enero de 2020 21:57
  • no mme muestra nada de una me salta el siguiente error,"No se pudieron habilitar las restricciones. Una o varias filas contienen valores que infringen las restricciones NON-NULL, UNIQUE o FOREIGN-KEY."

     este es el metodo en el que llamo el procedimiento almacenado 

      public static DsRemision.SACLIEDataTable ConsultaCliente(string codCliente)
            {
                
                return adapter.GetConsultarC(codCliente);
            }


    Daniel

    martes, 28 de enero de 2020 13:40
  • ese GetconsultarC es un Alias que le doy al procedimiento almacenado SeleccionarCliente

    Daniel


    martes, 28 de enero de 2020 17:57
  • Hola Dannycv012:

    La mejora manera de saber lo que ocurre es preguntarle a los participantes.

    ¿Y como le preguntamos al sql server? Para esto la opción más fácil, es utilizar el Sql Server Profiler.

    Prepara la aplicación. Pon un punto de interrupción, antes de la llamada al procedure.

    Arranca el Sql server profiler. Desde el Sql server managment Studio en el menú de herramientas. O desde Windows Microsoft Sql Server Tools

    Conectate al servidor sql.

    Cambia el selector hasta, Usar la plantilla en blanco, y pulsa en la siguiente pestaña, Selección de eventos.

    Marca RPC Completed y ejecutar (esto no se puede hacer en producción porque genera un coste importante).

    Ahora el profiler capturará las peticiones que le lleguen al sql server, para ejecutar tú procedure. Y verás las sentencias que se estan ejecutando.

    Vuelves a visual studio donde tienes el código parado, y vas pulsando F11 ejecutando paso a paso, instrucción por instrucción, hasta ver la query que le manda tú código al sql server.

    Yo tengo el punto de interrupción, justo antes de ejecutar conn.Open(); en este ejemplo de código.

    Nada más que paso a ejecutar la sentencia var result= bd.ExecuteReader();, en el profiler veo la petición de ejecución que le hace mí código al procedure.

    En la parte superior veo, la petición, con mucha informacíon, y en la parte de abajo, veo explicitamente la sentencia.

    En este caso exec [dbo].[sp_acceso] @usuario=1

    Esta es la sentencia que ejecuta mi código.

    Creo que así puedes saber porque se vuelve loco. Algo no va a funcionar como tú crees.

    martes, 28 de enero de 2020 21:22
  • javier muchas gracia s por este aporte , mira esto es lo que me arroja  cuando corro el profile

    Daniel


    miércoles, 29 de enero de 2020 13:55
  • Hola Daniel:

    me devuelve la totalidad de las columnas en sql

    En la primera parte de la pregunta, decías que tenías una tabla con muchas columnas, pero que el procedimiento solo recuperaba unas pocas.

    ¿Son las que te devuelve?

    Por cierto tu procedure, tal cual lo has expresado no esta bien.

    ALTER PROC SeleccionarCliente @codclie VARCHAR(50)
    AS
        BEGIN
            SELECT Descrip
                 , TipoID
                 , Direc1
                 , Direc2
                 , Pais
                 , Estado
                 , Ciudad
                 , Municipio
                 , Telef
                 , Movil
                 , Email
                 , CodVend
                 , CodConv
                 , Observa
                 , EsCredito
            FROM 
                 SACLIE
                   WHERE CodClie = @codclie;
        END;

    Observa que el Where te lo he cambiado por el parámetro recibido.

    Luego tendrás que actualizar tu dataset.

    Como en esta conversación.

    https://social.technet.microsoft.com/Forums/es-ES/ed3a10a3-bfeb-4e0a-82b3-cc65b3d99258/error-al-agregar-columna?forum=sqlserveres

    miércoles, 29 de enero de 2020 18:35
  • Hola Dannycv012:

    Empecemos por partes. Voy a crear la tabla en sql server y a insertar una fila (tu esto no lo haces porque ya lo tienes). Nota he puesto todas las columnas como varchar, pero era por facilidad. Pueden ser del tipo que realmente sean.

    CREATE TABLE SACLIE (
      CODCLIE		VARCHAR(100)
    , DESCRIPCION	        VARCHAR(100)
    , TIPOID		VARCHAR(100)
    , DIREC1		VARCHAR(100)
    , DIREC2		VARCHAR(100)
    , PAIS			VARCHAR(100)
    , ESTADO		VARCHAR(100)
    , CIUDAD		VARCHAR(100)
    , MUNICIPIO		VARCHAR(100)
    , TELEF			VARCHAR(100)
    , MOVIL			VARCHAR(100)
    , EMAIL			VARCHAR(100)
    , CODVEND		VARCHAR(100)
    , CODCONV		VARCHAR(100)
    , OBSERVA		VARCHAR(100)
    , ESCREDITO		VARCHAR(100)
    )
    GO
    INSERT INTO SACLIE (CODCLIE, DESCRIPCION,TIPOID, DIREC1, DIREC2, PAIS  , ESTADO
    , CIUDAD, MUNICIPIO, TELEF , MOVIL , EMAIL , CODVEND, CODCONV, OBSERVA, ESCREDITO)
    VALUES 
    ('24318655','DES','TIPO','DIRE','DIRE2','PAIS','ESTADO','CIUDAD','MUNICIPIO','TELEF','MOVIL','EMAIL','CONVEND','COD','OBSERVA','CREDITO');
    GO

    Ya tengo una tabla y una fila. Ahora voy a crear un procedure que me recupera una serie de columnas de la tabla.

    CREATE PROC SeleccionarUnCliente @codclie VARCHAR(50)
    AS
        BEGIN
            SELECT TOP(1) 
    			  CODCLIE
    			 , DESCRIPCION
                 , TipoID
                 , Direc1
                 , Direc2
                 , Pais
                 , Estado
                 , Ciudad
                 , Municipio
                 , Telef
                 , Movil
                 , Email
                 , CodVend
                 , CodConv
                 , Observa
                 , EsCredito
            FROM 
                 SACLIE
                   WHERE CodClie = @codclie;
        END;

    Fíjate que he llamado al procedimiento SeleccionarUnCliente y no seleccionar cliente, porque dentro he puesto el operador top, de manera que como mucho me devolverá una fila. Esto lo hago porque tú estas asignando el resultado a objetos textBox, por tanto solo esperas un resultado.

                string user = "24318655";
                string resultadoColumna1 = string.Empty;
                string constr = @"Persist Security Info=False;Integrated Security=true;Initial Catalog=Estudiantes;Server=ESQUINERO";
                SqlConnection conn = new SqlConnection(constr);
                using (SqlConnection con = new SqlConnection(constr))
                {
                    SqlCommand bd = new SqlCommand("[dbo].[SeleccionarUnCliente]");
    
                    bd.CommandType = CommandType.StoredProcedure;
    
                    conn.Open();
    
                    bd.Parameters.AddWithValue("@codClie", user);
                   
                    bd.Connection = conn;
                    
                    SqlDataReader reader = bd.ExecuteReader();
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            resultadoColumna1 = reader.GetString(0);
    
                            /// aqui tienes todos los datos Que en nuestro caso, serán todas las columnas y 1 sola fila por el operador top
                        }
                    }
                    reader.Close();
                }

    Aquí ya hay algunas diferencias entre tú código y el mio.

    Lo primero, obvio, que nuestra cadena de conexión la hemos puesto diferente.

    Fíjate que he utilizado un bloque using para SqlConnection, así ocurra lo que ocurra no me tengo que preocupar de consumir close o dispose para liberar recursos, pues el bloque using lo hará por mi.

    Siguiente paso, importante, el parámetro que quiere el procedimiento almacenado, yo solo le doy el parametro y el se encarga de la gestión. En tú caso ahora mismo, no cambia mucho, pero cuando trabajes con fechas, por ejemplo esto es muy importante, porque punto net se encargará de hablar con Sql en el formato que corresponda y no te generará problemas de conversión.

    Además evita las inyecciones sql.

    Luego he usado un SqlDataReader. Simplemente porque tú en la última ventana de código lo usas.

    Fíjate que del datareader, leo si tiene filas, y si las tiene las recorro. Ya se que tiene una sola, pero el código es igual.

    Del dataReader, puedes obtener las columnas con sus funciones GetString, GetInteger....etc.

    A partír de ahi, tú mismo recupera los valores de las columnas y se los asignas a tus objetos (textBox y demás)

    Recuperar datos con Datareader

    https://docs.microsoft.com/es-es/dotnet/framework/data/adonet/retrieving-data-using-a-datareader

    miércoles, 29 de enero de 2020 21:43

Todas las respuestas

  • Hola Dannycv012:

    Estás seguro de que llamas al procedure?

    Cuantas rows te devuelve?


    lunes, 27 de enero de 2020 21:57
  • no mme muestra nada de una me salta el siguiente error,"No se pudieron habilitar las restricciones. Una o varias filas contienen valores que infringen las restricciones NON-NULL, UNIQUE o FOREIGN-KEY."

     este es el metodo en el que llamo el procedimiento almacenado 

      public static DsRemision.SACLIEDataTable ConsultaCliente(string codCliente)
            {
                
                return adapter.GetConsultarC(codCliente);
            }


    Daniel

    martes, 28 de enero de 2020 13:40
  • Un procedimiento almacenado con una select, no parece lógico que te devuelva ese error.

    Según tu primera anotación el procedimiento sql server se llama:

    SeleccionarCliente y recibe un parámetro.

    En ese GetConsultarC(codCliente) que código hay?


    martes, 28 de enero de 2020 16:56
  • ese GetconsultarC es un Alias que le doy al procedimiento almacenado SeleccionarCliente

    Daniel


    martes, 28 de enero de 2020 17:57
  • Hola Dannycv012:

    La mejora manera de saber lo que ocurre es preguntarle a los participantes.

    ¿Y como le preguntamos al sql server? Para esto la opción más fácil, es utilizar el Sql Server Profiler.

    Prepara la aplicación. Pon un punto de interrupción, antes de la llamada al procedure.

    Arranca el Sql server profiler. Desde el Sql server managment Studio en el menú de herramientas. O desde Windows Microsoft Sql Server Tools

    Conectate al servidor sql.

    Cambia el selector hasta, Usar la plantilla en blanco, y pulsa en la siguiente pestaña, Selección de eventos.

    Marca RPC Completed y ejecutar (esto no se puede hacer en producción porque genera un coste importante).

    Ahora el profiler capturará las peticiones que le lleguen al sql server, para ejecutar tú procedure. Y verás las sentencias que se estan ejecutando.

    Vuelves a visual studio donde tienes el código parado, y vas pulsando F11 ejecutando paso a paso, instrucción por instrucción, hasta ver la query que le manda tú código al sql server.

    Yo tengo el punto de interrupción, justo antes de ejecutar conn.Open(); en este ejemplo de código.

    Nada más que paso a ejecutar la sentencia var result= bd.ExecuteReader();, en el profiler veo la petición de ejecución que le hace mí código al procedure.

    En la parte superior veo, la petición, con mucha informacíon, y en la parte de abajo, veo explicitamente la sentencia.

    En este caso exec [dbo].[sp_acceso] @usuario=1

    Esta es la sentencia que ejecuta mi código.

    Creo que así puedes saber porque se vuelve loco. Algo no va a funcionar como tú crees.

    martes, 28 de enero de 2020 21:22
  • javier muchas gracia s por este aporte , mira esto es lo que me arroja  cuando corro el profile

    Daniel


    miércoles, 29 de enero de 2020 13:55
  • Hola Dannycv012:

    Si ejecutas eso en el Sql Server

    exec..... explicitamente, cuanto tarda en resolver? No vaya a ser que tengas un problema de parameter sniffing.

    miércoles, 29 de enero de 2020 15:59
  • ejecutandolo en sql server la respuesta es  inmediata

    Daniel

    miércoles, 29 de enero de 2020 16:27
  • Ok. Y el número de columnas que te devuelve el Sql son las que tienen que devolver.

    Ejecutando paso por paso, donde se te detiene?. Te llega a llenar el dataset

    miércoles, 29 de enero de 2020 16:46
  • me devuelve  la totalidad de las columnas en sql  , en el paso a paso en C#  se detiene en el metodo que llama el  procedimiento almacenado, en este paso se detiene

    public static DsRemision.SACLIEDataTable ConsultaCliente(string codCliente)
            {
                
                return adapter.GetConsultarC(codCliente);
            }

     

    Daniel

    miércoles, 29 de enero de 2020 16:50
  • Hola Daniel:

    me devuelve la totalidad de las columnas en sql

    En la primera parte de la pregunta, decías que tenías una tabla con muchas columnas, pero que el procedimiento solo recuperaba unas pocas.

    ¿Son las que te devuelve?

    Por cierto tu procedure, tal cual lo has expresado no esta bien.

    ALTER PROC SeleccionarCliente @codclie VARCHAR(50)
    AS
        BEGIN
            SELECT Descrip
                 , TipoID
                 , Direc1
                 , Direc2
                 , Pais
                 , Estado
                 , Ciudad
                 , Municipio
                 , Telef
                 , Movil
                 , Email
                 , CodVend
                 , CodConv
                 , Observa
                 , EsCredito
            FROM 
                 SACLIE
                   WHERE CodClie = @codclie;
        END;

    Observa que el Where te lo he cambiado por el parámetro recibido.

    Luego tendrás que actualizar tu dataset.

    Como en esta conversación.

    https://social.technet.microsoft.com/Forums/es-ES/ed3a10a3-bfeb-4e0a-82b3-cc65b3d99258/error-al-agregar-columna?forum=sqlserveres

    miércoles, 29 de enero de 2020 18:35
  • javier eh buscado otra forma y asi trata de traer los datos  , pero no me muestra nada  en los controles del formulario , soy novato aun en muchas cosas como podria cargar ahi  mi procedimiento almacenado , 

     var  cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
               var con = new SqlConnection(cs);
                SqlDataAdapter da;
                DataTable dt;

                string id = txtDocClie.Text;
                da = new SqlDataAdapter(" Select CodClie, Descrip,TipoID,Direc1," +
                    " Direc2,Pais,Estado,Ciudad,Municipio,Telef,Movil,Email,CodVend," +
                    " CodConv,Observa,EsCredito from SACLIE where CodClie ='"+id+"'", con);
                dt = new DataTable();
                da.Fill(dt);
                txtDocClie.Text = dt.Rows[0][0].ToString();
                txtDesClie.Text = dt.Rows[0][1].ToString();
                drpTDCliente.SelectedValue = dt.Rows[0][2].ToString();
                txtDirClie1.Text = dt.Rows[0][3].ToString();
                txtDirClien2.Text = dt.Rows[0][4].ToString();
                drpPais.SelectedValue = dt.Rows[0][5].ToString();
                drpEstado.SelectedValue = dt.Rows[0][6].ToString();
                drpCiudad.SelectedValue = dt.Rows[0][7].ToString();
                drpMunicipio.SelectedValue = dt.Rows[0][8].ToString();
                txtTelClie.Text = dt.Rows[0][9].ToString();
                txtcelClie.Text = dt.Rows[0][10].ToString();
                txtEmailClie.Text = dt.Rows[0][11].ToString();
                drpVendedor.SelectedValue = dt.Rows[0][12].ToString();
                drpConClie.SelectedValue = dt.Rows[0][13].ToString();
                TextareaClie.InnerText = dt.Rows[0][14].ToString();
              int  credito = Convert.ToInt32(dt.Rows[0][15].ToString());
                if (credito == 1) { chboxcredito.Checked = true; }
                else { chboxcredito.Checked = false; }

                

                return ;
            }


    Daniel


    • Editado Dannycv012 miércoles, 29 de enero de 2020 21:11
    miércoles, 29 de enero de 2020 21:05
  • Hola Dannycv012:

    Empecemos por partes. Voy a crear la tabla en sql server y a insertar una fila (tu esto no lo haces porque ya lo tienes). Nota he puesto todas las columnas como varchar, pero era por facilidad. Pueden ser del tipo que realmente sean.

    CREATE TABLE SACLIE (
      CODCLIE		VARCHAR(100)
    , DESCRIPCION	        VARCHAR(100)
    , TIPOID		VARCHAR(100)
    , DIREC1		VARCHAR(100)
    , DIREC2		VARCHAR(100)
    , PAIS			VARCHAR(100)
    , ESTADO		VARCHAR(100)
    , CIUDAD		VARCHAR(100)
    , MUNICIPIO		VARCHAR(100)
    , TELEF			VARCHAR(100)
    , MOVIL			VARCHAR(100)
    , EMAIL			VARCHAR(100)
    , CODVEND		VARCHAR(100)
    , CODCONV		VARCHAR(100)
    , OBSERVA		VARCHAR(100)
    , ESCREDITO		VARCHAR(100)
    )
    GO
    INSERT INTO SACLIE (CODCLIE, DESCRIPCION,TIPOID, DIREC1, DIREC2, PAIS  , ESTADO
    , CIUDAD, MUNICIPIO, TELEF , MOVIL , EMAIL , CODVEND, CODCONV, OBSERVA, ESCREDITO)
    VALUES 
    ('24318655','DES','TIPO','DIRE','DIRE2','PAIS','ESTADO','CIUDAD','MUNICIPIO','TELEF','MOVIL','EMAIL','CONVEND','COD','OBSERVA','CREDITO');
    GO

    Ya tengo una tabla y una fila. Ahora voy a crear un procedure que me recupera una serie de columnas de la tabla.

    CREATE PROC SeleccionarUnCliente @codclie VARCHAR(50)
    AS
        BEGIN
            SELECT TOP(1) 
    			  CODCLIE
    			 , DESCRIPCION
                 , TipoID
                 , Direc1
                 , Direc2
                 , Pais
                 , Estado
                 , Ciudad
                 , Municipio
                 , Telef
                 , Movil
                 , Email
                 , CodVend
                 , CodConv
                 , Observa
                 , EsCredito
            FROM 
                 SACLIE
                   WHERE CodClie = @codclie;
        END;

    Fíjate que he llamado al procedimiento SeleccionarUnCliente y no seleccionar cliente, porque dentro he puesto el operador top, de manera que como mucho me devolverá una fila. Esto lo hago porque tú estas asignando el resultado a objetos textBox, por tanto solo esperas un resultado.

                string user = "24318655";
                string resultadoColumna1 = string.Empty;
                string constr = @"Persist Security Info=False;Integrated Security=true;Initial Catalog=Estudiantes;Server=ESQUINERO";
                SqlConnection conn = new SqlConnection(constr);
                using (SqlConnection con = new SqlConnection(constr))
                {
                    SqlCommand bd = new SqlCommand("[dbo].[SeleccionarUnCliente]");
    
                    bd.CommandType = CommandType.StoredProcedure;
    
                    conn.Open();
    
                    bd.Parameters.AddWithValue("@codClie", user);
                   
                    bd.Connection = conn;
                    
                    SqlDataReader reader = bd.ExecuteReader();
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            resultadoColumna1 = reader.GetString(0);
    
                            /// aqui tienes todos los datos Que en nuestro caso, serán todas las columnas y 1 sola fila por el operador top
                        }
                    }
                    reader.Close();
                }

    Aquí ya hay algunas diferencias entre tú código y el mio.

    Lo primero, obvio, que nuestra cadena de conexión la hemos puesto diferente.

    Fíjate que he utilizado un bloque using para SqlConnection, así ocurra lo que ocurra no me tengo que preocupar de consumir close o dispose para liberar recursos, pues el bloque using lo hará por mi.

    Siguiente paso, importante, el parámetro que quiere el procedimiento almacenado, yo solo le doy el parametro y el se encarga de la gestión. En tú caso ahora mismo, no cambia mucho, pero cuando trabajes con fechas, por ejemplo esto es muy importante, porque punto net se encargará de hablar con Sql en el formato que corresponda y no te generará problemas de conversión.

    Además evita las inyecciones sql.

    Luego he usado un SqlDataReader. Simplemente porque tú en la última ventana de código lo usas.

    Fíjate que del datareader, leo si tiene filas, y si las tiene las recorro. Ya se que tiene una sola, pero el código es igual.

    Del dataReader, puedes obtener las columnas con sus funciones GetString, GetInteger....etc.

    A partír de ahi, tú mismo recupera los valores de las columnas y se los asignas a tus objetos (textBox y demás)

    Recuperar datos con Datareader

    https://docs.microsoft.com/es-es/dotnet/framework/data/adonet/retrieving-data-using-a-datareader

    miércoles, 29 de enero de 2020 21:43
  • Javier muchas gracias por tu ayuda  me han servido tus consejos para aprender cosas nuevas , lo ultimo que me enviaste funciona muy bien , realice el seguimiento con profile y corre excelente , pero no me logra traer los datos a los controles textbox ya estoy mirando si el error esta en el codebin en c#

    Daniel


    • Editado Dannycv012 jueves, 30 de enero de 2020 15:41
    jueves, 30 de enero de 2020 15:40