Usuario
Procedimiento Almacenado no Actualiza Tabla

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
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
- Editado Willams Morales 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
saludos
Leandro Tuttini
Blog
MVP Profile
Buenos Aires
Argentina- Propuesto como respuesta Sergio ParraModerator martes, 29 de diciembre de 2015 9:56
-
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