none
Función para obtener resultado de un stored procedure con varios resultados RRS feed

  • Pregunta

  • Buenos días, les comento que tengo un estored procedure que me brinda el siguiente resultado

    ID       Parcialidad Cantidad

    5291 495 1 20685.32
    5292 495 2 20685.32
    5293 495 3 20685.32
    5294 495 4 20685.32
    5295 495 5 20685.32
    5296 495 6 20685.32
    5297 495 7 20685.32
    5298 495 8 20685.32
    5299 495 9 20685.32
    5300 495 10 20685.29

    Lo cual estoy intentando de ejecutar el stored procedure desde C# con la siguiente funcion

    public List<TodaClase> GetConsultaXParcialidad(string IdContrato)
            {
                var FullData = new List<TodaClase>(); var Data = new List<TodaClase>();
                SqlConnection con = new SqlConnection(ConexionMora);
                SqlDataAdapter sda = new SqlDataAdapter();
                DataTable dt = new DataTable();
                DataSet ds = new DataSet();

                con.Open();
                sda.SelectCommand = new SqlCommand("[darm_spCONSULTAXPARCIALIDAD]", con);
                sda.SelectCommand.CommandType = CommandType.StoredProcedure;
                sda.SelectCommand.Parameters.Add("@IdContrato", SqlDbType.VarChar).Value = IdContrato;
                sda.Fill(dt);

                Data = dt.AsEnumerable().Select(m => new TodaClase()
                {
                    IntColumna01 = m.Field<int>("Idparcialidad"),
                    IntColumna02 = m.Field<int>("IdContratoXejercicio"),
                    IntColumna03 = m.Field<int>("Noparcialidad"),
                    DecimalColumna01 = m.Field<Decimal>("ImportePacial")
                }).ToList();

                return Data;
            }

    El problema que me da es que cuando lo ejecuto me dice que el stored procedure esta brindando varios resultados los cuales no los puede almacenar en la siguiente funcion 


    Jonathan Samayoa


    viernes, 21 de agosto de 2020 17:53

Respuestas

  • Bien, el error ya está claro. Al ver el mensaje se reconoce exactamente qué es. No es un error en el código llamante, sino que es uno de los errores que devuelve SQL Server cuando ocurre la circunstancia de que usas una subconsulta que devuelve varios valores en un sitio donde solo se admite un valor. Por ejemplo, algo similar a esto:

    select ... from tabla 1 where campo1=(select campo2 from tabla2)

    Si tabla2 en este ejemplo tiene más de un registro, entonces la segunda select devuelve más de un valor, y como campo1 no se puede igualar nada más que a un único valor, entonces SQL Server arroja un error que es precisamente idéntico al que has mostrado en tu captura de pantalla.

    El problema es que no veo en el código de tu procedimiento almacenado ninguna ocurrencia de una subconsulta de este tipo, por lo que es inexplicable que presente este mensaje de error.

    La única explicación que se me ocurre es que no estés llamando al mismo procedimiento cuyo código hemos visto en un mensaje anterior, sino que por alguna causa estés llamando a otro procedimiento distinto. No sería la primera vez, ya ha habido alguna pregunta anterior en estos foros en la que al final lo que ocurría es que el desarrollador había escrito mal una letra en el nombre del procedimiento, con lo que el procedimiento que llamaba desde el cliente era una versión antigua del que había en el servidor, y no el último que había creado.

    lunes, 24 de agosto de 2020 7:08
    Moderador

Todas las respuestas

  •  tengo un estored procedure que me brinda el siguiente resultado

    La pregunta es cómo lo devuelve. Es importante porque hay dos formas en las que puede hacerlo, y dependiendo de cuál sea, los resultados se recogen de distinta manera desde el código llamante.

    Si el procedimiento devuelve varios registros como resultado de una única sentencia Select, entonces se pueden recibir como estás haciendo, es decir, con un dataadapter y el método Fill. También se puede usar un datareader. Si tu caso es este, y a pesar de ello no funciona, entonces hacen falta más detalles; tendríamos que ver el mensaje de error exacto, completo y detallado.

    Pero si el procedimiento devuelve los valores como resultado de ejecutar varias Select, entonces en el lado cliente el Fill o el DataReader solo recuperarían en resultado de la primera select. Para pasar a la siguiente es necesario usar un SqlDataReader y llamar a su método NextResult para ir avanzando de una Select a la otra. Si es necesario podemos buscar un ejemplo, pero antes sería conveniente tener respuesta sobre cuál de los dos mecanismos está usando el procedimiento (y ya de paso, el mensaje de error exacto y completo).

    viernes, 21 de agosto de 2020 19:28
    Moderador
  • Buena tarde, 

    Muchas gracias por tu pronta respuesta te comento que este es el stored que estoy utilizando

    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @Parcialidades TABLE(
    Idparcialidad INT,
    IdContratoXejercicio INT,
    Noparcialidad INT,
    ImportePacial MONEY
    )
    INSERT INTO @Parcialidades

    select A.Id_Parcialidad, A.Id_ContratoXEjercicio, A.NumeroParcial, A.ImporteParcial from darm_tblPARCIALIDAD A
    INNER JOIN @ContratoXsuficiencia B ON A.Id_ContratoXEjercicio = B.IdContratoXsuficiencia

    SELECT * FROM @Parcialidades 
    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    END
    GO

    lo cual el resultado de esa consulta me devuelve la siguiente tabla

    ID       Parcialidad Cantidad

    5291 495  1 20685.32
    5292 495  2 20685.32
    5293 495  3 20685.32
    5294 495  4 20685.32
    5295 495  5 20685.32
    5296 495  6 20685.32
    5297 495  7 20685.32
    5298 495  8 20685.32
    5299 495  9 20685.32
    5300 495  10 20685.29

    Gracias


    Jonathan Samayoa

    viernes, 21 de agosto de 2020 20:31
  • Bien, entonces estamos en el primer caso (solo contiene una única Select que devuelva datos).

    Por cierto, el procedimiento es "muy tonto" en el sentido de que ejecuta una select que inserta su resultado en una tabla temporal, y a continuación devuelve el resultado de la tabla temporal. Para eso, daría lo mismo devolver directamente el resultado de la primera select, sin usar la tabla temporal (que es costoso e ineficiente). Pero esto no es motivo de que ocasione ningún error, simplemente es poco eficiente.

    Pero hay algo que me preocupa: En la llamada le pasas un parámetro "@IdContrato", pero en el fragmento de procedimiento que has pegado no se ve que ese parámetro se use para nada. Eso por sí solo no es causa de que se produzca un error, pero nos lleva a pensar que "hay algo raro". Tal vez el procedimiento hace otras operaciones que no se ven en tu mensaje. Entre otras cosas, hace un join con otra tabla temporal, que ha tenido que construir en algún sitio. Convendría revisarlo, no vaya a ser que se haya escapado alguna "select" que devuelva datos en la parte de código que construye dicha tabla.

    En cualquier caso, si el procedimiento solo tiene lo que vemos, la llamada que haces debería ser capaz de recoger los resultados. Si falla, es el momento de examinar con todo detenimiento el mensaje de error. Cópialo al completo y con toda exactitud y ponlo aquí para que podamos analizarlo.


    sábado, 22 de agosto de 2020 5:55
    Moderador
  • Buenos días te adjunto todo el codigo del stored procedure, la tabla temporal es por que lo que voy haciendo es que consulta datos en diferentes tablas y el resultado lo voy pasando a otra para que al final sacar el resultado final que es el ultimo que dice Parcialidades.

    el set lo tengo por que es con lo que pruebo para ver la funcionalidad de mi stored el cual con esto logro ver que mi consulta brinda la informacion que busco. pero para usarlo en el stored le quito el set y dejo declarada la variabla de @IdContrato la cual se la mando desde la programacion

    DECLARE @IdContrato VARCHAR (50)

    SET @IdContrato = '2020Contrato_NEJu9d2xBbgfZaNQ1'


    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS NOMBRE CONTRATO*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblCONTRATOxDATO TABLE(
    IdContratoXDato INT
    )
    INSERT INTO @tblCONTRATOxDATO
    SELECT(
    select Id_ContratoXDato from darm_tblCONTRATOxDATO where Id_Contrato = @IdContrato
    )
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS CONTRATO POR EJERCICIO*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblCONTRATOxEJERCICIO TABLE(
    IdContratoXEjercicio INT
    )
    INSERT INTO @tblCONTRATOxEJERCICIO
    SELECT(
    select Id_ContratoXEjercicio from darm_tblCONTRATOxEJERCICIO A
    INNER JOIN @tblCONTRATOxDATO B ON A.Id_ContratoXDato = B.IdContratoXDato
    )
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS LA SUFIENCIA X FF*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblCONTRATOxFF TABLE(
    IdContratoXFF INT
    )
    INSERT INTO @tblCONTRATOxFF
    SELECT(
    select A.Id_ContratoXFF from darm_tblCONTRATOxFF A
    INNER JOIN @tblCONTRATOxEJERCICIO B ON A.Id_ContratoXEjercicio = B.IdContratoXEjercicio
    WHERE A.Inhabilitado = 0
    )
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS CONTRATO X EJERCICIO*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblCONTRATOxCC TABLE(
    IdContratoXCC INT
    )
    INSERT INTO @tblCONTRATOxCC
    SELECT(
    select A.Id_ContratoXCC from darm_tblCONTRATOxCC A
    INNER JOIN @tblCONTRATOxFF B ON A.Id_ContratoXFF = B.IdContratoXFF
    WHERE A.Inhabilitado = 0
    )
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS CONTRATO X SUFICIENCIA*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblCONTRATOxSUFICIENCIA TABLE(
    IdContratoXSuficiencia INT
    )
    INSERT INTO @tblCONTRATOxSUFICIENCIA
    SELECT(
    select A.Id_ContratoXSuficiencia from darm_tblCONTRATOxSUFICIENCIA A
    INNER JOIN @tblCONTRATOxEJERCICIO B ON A.Id_ContratoXEjercicio = B.IdContratoXEjercicio
    WHERE A.Inhabilitado = 0
    )
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    /*OBTENEMOS CONTRATO X EJERCICIO*/
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    DECLARE @tblPARCIALIDAD TABLE(
    IdParcialidad INT,
    IdContratoXEjercicio INT,
    ImporteParcial MONEY,
    ParcialidadAplicada INT
    )
    INSERT INTO @tblPARCIALIDAD

    select A.Id_Parcialidad, A.Id_ContratoXEjercicio, A.ImporteParcial, A.ParcialAplicada from darm_tblPARCIALIDAD A
    INNER JOIN @tblCONTRATOxEJERCICIO B ON A.Id_ContratoXEjercicio = B.IdContratoXEjercicio

    SELECT * FROM @tblPARCIALIDAD


    Jonathan Samayoa

    domingo, 23 de agosto de 2020 16:39
  • Sí, está bien, porque todas las ocurrencias del select son insert...select, así que solo queda el último select para devolver resultados.

    Por lo tanto no tendrás más remedio que hacer la otra cosa que hemos dicho en los dos mensajes anteriores, y en la que te insisto por tercera vez: "... es el momento de examinar con todo detenimiento el mensaje de error. Cópialo al completo y con toda exactitud y ponlo aquí para que podamos analizarlo".

    domingo, 23 de agosto de 2020 18:59
    Moderador
  • Buena tarde, 

    Te adjunto el mensaje del error que me da y la forma en la que estoy utilizando la funcionn en C#

    error


    Jonathan Samayoa

    domingo, 23 de agosto de 2020 21:08
  • Bien, el error ya está claro. Al ver el mensaje se reconoce exactamente qué es. No es un error en el código llamante, sino que es uno de los errores que devuelve SQL Server cuando ocurre la circunstancia de que usas una subconsulta que devuelve varios valores en un sitio donde solo se admite un valor. Por ejemplo, algo similar a esto:

    select ... from tabla 1 where campo1=(select campo2 from tabla2)

    Si tabla2 en este ejemplo tiene más de un registro, entonces la segunda select devuelve más de un valor, y como campo1 no se puede igualar nada más que a un único valor, entonces SQL Server arroja un error que es precisamente idéntico al que has mostrado en tu captura de pantalla.

    El problema es que no veo en el código de tu procedimiento almacenado ninguna ocurrencia de una subconsulta de este tipo, por lo que es inexplicable que presente este mensaje de error.

    La única explicación que se me ocurre es que no estés llamando al mismo procedimiento cuyo código hemos visto en un mensaje anterior, sino que por alguna causa estés llamando a otro procedimiento distinto. No sería la primera vez, ya ha habido alguna pregunta anterior en estos foros en la que al final lo que ocurría es que el desarrollador había escrito mal una letra en el nombre del procedimiento, con lo que el procedimiento que llamaba desde el cliente era una versión antigua del que había en el servidor, y no el último que había creado.

    lunes, 24 de agosto de 2020 7:08
    Moderador
  • Muchas gracias por tu apoyo voy a verificar bien el nombre del stored Procedure que estoy llamando aunque el nombre si esta correcto por que lo copie del stored.


    Jonathan Samayoa

    lunes, 24 de agosto de 2020 15:42