none
Procedimiento Almacenado no Actualiza Tabla RRS feed

  • Pregunta

  • Hola Muchachos,

    Quisiera pedirles su ayuda... Resulta que tengo un formulario web en el cual tengo un gridview con un dropdownlist, que contiene estados (Abierto-En Proceso-Finalizado), y un botón actualizar que me permite guardar el cambio del estado a través de un procedimiento almacenado.

    Probe pasar el ID y el Estado de la fila a 2 labels para verificar que los datos correspondian a los mostrados en dicha fila.

    El problema es que al momento de asignar ID y ESTADO al procedimiento, este no me guarda los cambios en la tabla de sql server.

    Les dejo el código de mi procedimiento almacenado en visual studio 2010 y sql server 2008:

    Public Shared Function ActualizarEstadoIncidente(ByVal idincidente As Integer, _
                                                    ByVal Estado As Integer) As Boolean
    
    
    
            Dim comando As New SqlCommand
            With comando
                .Connection = SQL_Conexion()
                .Parameters.Clear()
                .CommandType = Data.CommandType.StoredProcedure
                .CommandText = "SP_ActualizarEstadoIncidente"
                .Parameters.Add("@idincidente", Data.SqlDbType.Int).Direction = Data.ParameterDirection.Input
                .Parameters.Add("@estado", Data.SqlDbType.Int).Direction = Data.ParameterDirection.Input
    
                .Parameters.Add("@estcod", Data.SqlDbType.Int).Direction = Data.ParameterDirection.Output
                .Parameters.Add("@estmsg", Data.SqlDbType.Char, 200).Direction = Data.ParameterDirection.Output
    
                .Parameters("@idincidente").Value = idincidente
                .Parameters("@estado").Value = Estado
                .ExecuteNonQuery()
    
                mensajeBDI = .Parameters("@estmsg").Value.ToString()
                If .Parameters("@estcod").Value = 0 Then
                    Return True
                Else
                    Return False
                End If
            End With
    
    
        End Function


    ALTER PROCEDURE [dbo].[SP_ActualizarEstadoIncidente]
    
    @idincidente int,
    @estado int,
    @estcod int output,
    @estmsg char(200) output
    AS
    BEGIN
    	DECLARE @maxid int
    	SELECT @estcod = 0
    	SELECT @estmsg = 'El incidente fue guardado exitosamente'
    	
    		IF exists(SELECT 1 FROM Incidente WHERE Id_incidente = @idincidente)
    			
    			BEGIN
    				UPDATE Incidente
    				SET
    				Estado = @estado
    				WHERE Id_incidente = @idincidente
    			IF @estcod = 0
    
    				BEGIN
    					SELECT @estcod = 1
    					SELECT @estmsg = 'El incidente se actualizo satisfactoriamente'
    				END
    			ELSE
    				BEGIN
    					SELECT @estcod = 0
    					SELECT @estmsg = 'El incidente no se logro actualizar'
    				END
    
    			END
    
    END

    Protected Sub dgvIncidenteEncargado_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles dgvIncidenteEncargado.RowCommand
    
            If (e.CommandName = "boton") Then
                Dim ESTADOINT As Integer = 0
                Dim rowIndex As Integer = Convert.ToInt32(e.CommandArgument)
    
                Dim ID As Integer = Convert.ToString(dgvIncidenteEncargado.DataKeys(Convert.ToUInt32(e.CommandArgument)).Value)
                'Dim ESTADO As String = dgvIncidenteEncargado.DataKeys(rowIndex).Values(8).ToString()
    
                If (dgvIncidenteEncargado.DataKeys(rowIndex).Values(8).ToString().Trim = "Abierto") Then
                    ESTADOINT = 1
                Else
                    If (dgvIncidenteEncargado.DataKeys(rowIndex).Values(8).ToString().Trim = "En Proceso") Then
                        ESTADOINT = 2
                    Else
                        If (dgvIncidenteEncargado.DataKeys(rowIndex).Values(8).ToString().Trim = "Finalizado") Then
                            ESTADOINT = 3
                        End If
                    End If
                End If
    
                'Actuaizando Estado en la base de datos
                ActualizarEstadoIncidente(ID, ESTADOINT)
    
            End If
    
        End Sub

    Protected Sub dgvIncidenteEncargado_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles dgvIncidenteEncargado.RowDataBound
    
            If e.Row.RowType = DataControlRowType.DataRow Then
    
                Dim ddlEstado As DropDownList = CType(e.Row.FindControl("ddlEstado"), DropDownList)
    
                'Cargando ddlEstado con información almacenada en tabla ListaEncargado
                Dim dsEstado As New DataSet
                dsEstado = ObtenerEstado()
                Cargar_Objeto(dsEstado, "ddlEstado", ddlEstado, True)
    
                ddlEstado.DataSource = dsEstado.Tables(0)
                ddlEstado.DataTextField = "Nombre_estado"
                ddlEstado.DataValueField = "Nombre_estado"
    
                ddlEstado.DataBind()
    
                'Mostrando Estado desde base de datos
                Dim dr As DataRowView = TryCast(e.Row.DataItem, DataRowView)
                ddlEstado.SelectedValue = dr("Nombre_estado").ToString()
    
    
            End If
    
        End Sub

    Probe pasando los datos directamente en sql server y me actualiza sin problemas el estado.

    Cualquier ayuda será bienvenida!


    • Editado n4n2 lunes, 28 de diciembre de 2015 22:50 mas informacion
    lunes, 28 de diciembre de 2015 22:23

Todas las respuestas

  • Hola n4n2,

    Puntos:

    ¿Ya tienes una conexión abierta? Si no la tienes deberías abrirla y si la tienes deberías tenerla abierta sólo mientras dura la transacción y no dejarla abierta de manera global. ¿Te suena la instrucción Using para enmarcar el ámbito?

    Si estas instanciando un objeto de tipo SQLCommand se entiende que no tiene parametros "por default", es innecesario .Parameters.Clear().

    Los parámetros OUTPUT me parecen innecesarios, puedes validar si alguna operación fue afecta por el retorno de ExecuteNonQuery, el procedimiento debería quedarte de la siguiente manera:

    ALTER PROCEDURE [dbo].[SP_ActualizarEstadoIncidente]
            @idincidente int,
            @estado int
    AS
    BEGIN
            UPDATE Incidente
            SET
                    Estado = @estado
            WHERE 
                    (Id_incidente = @idincidente);
    
    END

    El código de la aplicación

    Dim comando As New SqlCommand
            With comando
                .Connection = SQL_Conexion()
                /*¿Dónde se abre la conexión?*/
                .CommandType = Data.CommandType.StoredProcedure
                .CommandText = "SP_ActualizarEstadoIncidente"
                .Parameters.AddWithVaue("@idincidente", idincidente)
                .Parameters.AddWithValue("@estado", Estado)
                
                int Resultado = Convert.ToInt32(ExecuteNonQuery())
                
                Return Resultado > 0
            End With



    lunes, 28 de diciembre de 2015 22:55
  • hola

    si pones un breakpoint en la ejecucion que mensaje devuelve el procedure ?

    lo que no entiendo es porque defines esta linea

    SELECT @estmsg = 'El incidente fue guardado exitosamente'

    ni bien inicia el procedure si ni siquiera sabes como va a resultar la operacion, deberias asignar un vacio a la variable output, cosa que si algo nos e ejecuta no recines ningun mensaje

    es mas que pasa si no ingresa al if de la linea

    IF exists(SELECT 1 FROMIncidente WHEREId_incidente = @idincidente)

    estaria recibiendo el mensaje que actualizo cuando esto seria incorrecto

    ---

    por otro lado porque el procedure devuelve un mensaje? no alcanzaria con solo tener el codigo para conocer si la operacion se realizo correctamente ?

    ALTER PROCEDURE [dbo].[SP_ActualizarEstadoIncidente]
    
    @idincidente int,
    @estado int,
    @estcod int output
    AS
    BEGIN
    	DECLARE @maxid int
    	SELECT @estcod = -1
    	
    		IF exists(SELECT 1 FROM Incidente WHERE Id_incidente = @idincidente)
    			
    			BEGIN
    				UPDATE Incidente
    				SET
    				Estado = @estado
    				WHERE Id_incidente = @idincidente
    				
    				SELECT @estcod = @@ROWCOUNT
    
    			END
    
    END

    no necesitas generar un mensaje, con el estado podrias validar si es un -1 no se afecto ningun registro, y sino devuelves los registros afectados

    @@ROWCOUNT (Transact-SQL)

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    lunes, 28 de diciembre de 2015 23:11
  • Hola n4n2,

    Puntos:

    ¿Ya tienes una conexión abierta? Si no la tienes deberías abrirla y si la tienes deberías tenerla abierta sólo mientras dura la transacción y no dejarla abierta de manera global. ¿Te suena la instrucción Using para enmarcar el ámbito?

    Si estas instanciando un objeto de tipo SQLCommand se entiende que no tiene parametros "por default", es innecesario .Parameters.Clear().

    Los parámetros OUTPUT me parecen innecesarios, puedes validar si alguna operación fue afecta por el retorno de ExecuteNonQuery, el procedimiento debería quedarte de la siguiente manera:

    ALTER PROCEDURE [dbo].[SP_ActualizarEstadoIncidente]
            @idincidente int,
            @estado int
    AS
    BEGIN
            UPDATE Incidente
            SET
                    Estado = @estado
            WHERE 
                    (Id_incidente = @idincidente);
    
    END

    El código de la aplicación

    Dim comando As New SqlCommand
            With comando
                .Connection = SQL_Conexion()
                /*¿Dónde se abre la conexión?*/
                .CommandType = Data.CommandType.StoredProcedure
                .CommandText = "SP_ActualizarEstadoIncidente"
                .Parameters.AddWithVaue("@idincidente", idincidente)
                .Parameters.AddWithValue("@estado", Estado)
                
                int Resultado = Convert.ToInt32(ExecuteNonQuery())
                
                Return Resultado > 0
            End With



    Hola Williams,

    Gracias por la pronta respuesta.

    Probé tus modificaciones, pero aun sigo sin poder actualizar el estado del registro donde presiono el botón actualizar.

    Revisando mas en profundidad, me di cuenta que el problema lo tengo en e botón ACTUALIZAR y el dropdownlist ESTADO, ya que al momento de cambiar el valor del dropdownlist, este no lo hace.

    Mira la conexión la abro con la línea 

    .Connection = SQL_Conexion()

    En cada clase que necesito usar procedimientos almacenados uso

    Imports ClsConexion

    la cual tiene lo siguiente:

    Public Shared Function SQL_Conexion() As SqlConnection
            Dim oconn As New SqlConnection(ConfigurationManager.ConnectionStrings("Conexion").ConnectionString)
            Try
                oconn.Open()
                Return oconn
            Catch ex As Exception
                oconn = Nothing
                Return oconn
            End Try
        End Function

    La línea de código que modificaste en el código de la aplicación:

    Tu me dices que me asegure de cerra la conexión cada vez que realizo un procedimiento almacenado?

    como podría hacerlo en el caso del procedimiento Actualizar que expuse mas arriba?

    Si dejo la conexión abierta, que problemas podría ocasionar?

    Espero me puedas ayudar con esas dudas

    Saludos y gracias!





    • Editado n4n2 martes, 29 de diciembre de 2015 18:16
    martes, 29 de diciembre de 2015 17:14