none
Transacciones dentro de clases RRS feed

  • Debate general

  • Hola buenas tardes,estoy desarrollando una palicacion de ventas en vb.net 2008 con bdd en mysql y mi consulta sobre transacciones es la siguiente:

    Es posible pasar las transacciones por parametros?, mi consulta es debido a que:

    Tengo una clase clasABMnumeracion y una ClasABMclientes con su respectivo GrabarDatos de clientes

    Public Class clasABMnumeracion
        Public Function getNumerodecliente(ByVal cn As MySqlConnection) As Integer 'obtengo numero
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Dim GetNumero As String = "SELECT `numeracion`.`numerodecliente` FROM `bdcomercio`.`numeracion`;"
            Dim cmdObtener As New MySqlCommand(GetNumero, cn)
            Dim drObtenerNumero As MySqlDataReader = cmdObtener.ExecuteReader
            drObtenerNumero.Read()
            Return drObtenerNumero.Item("numerodecliente")
        End Function
        Public Sub setNumerodecliente(ByVal cn As MySqlConnection) 'incremento numero
            Dim Transaccion As MySqlTransaction
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Transaccion = cn.BeginTransaction
            Try
                Dim setNumerodecliente As String = "UPDATE `bdcomercio`.`numeracion` SET `numerodecliente` = numerodecliente+1;"
                Dim cmdIncrementarNumero As New MySqlCommand(setNumerodecliente, cn)
                cmdIncrementarNumero.Transaction = Transaccion
                cmdIncrementarNumero.ExecuteNonQuery()
                Transaccion.Commit()
            Catch err As MySqlException
                Transaccion.Rollback()
            End Try
        End Sub
    End Class

    Public Class clasABMclientes

    ...............

    Public Sub GrabarCliente(ByVal cn As MySqlConnection)
            Dim Transaccion As MySqlTransaction
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Transaccion = cn.BeginTransaction
            Try
                Dim cadena1, cadena2, strInsertar As String
                cadena1 = "INSERT INTO `bdcomercio`.`cliente` (`idcliente`,`apellidoynombre`,`direccion`,`numero`,`localidad`,`telefono`,`iva`,`cuit`,`cuentacorriente`)"
                cadena2 = " VALUES (" & idcliente & ",'" & apellidonombrerazonsocial & "','" & direccion & "','" & numerodireccion & "','" & localidad & "','" & telefono & "','" & tipodeiva & "','" & cuit & "','" & cuentacorriente & "');"
                strInsertar = cadena1 + cadena2
                Dim cmdInsertar As New MySqlCommand(strInsertar, cn)
                cmdInsertar.Transaction = Transaccion
                cmdInsertar.ExecuteNonQuery()
                Transaccion.Commit()
            Catch err As MySqlException
                Transaccion.Rollback()
            End Try
        End Sub

    End Class

    Y en el boton grabar del formulario donde realizo el ingreso de los datos frmclientes

         Private Sub btngrabar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btngrabar.Click
            Dim cn, cn1 As New MySqlConnection
            Dim objConexion As New clasConexion
            Dim objNumeracion As New clasABMnumeracion
            Dim objClientes As New clasABMclientes
            Select Case opcion
                Case 1 ' grabar nuevo
                    Try
                        cn = objConexion.ConectarBd
                        cn1 = objConexion.ConectarBd
                        Dim numeroDeCliente As Integer = objNumeracion.getNumerodecliente(cn)
                        cn.Close()
                        With objClientes
                            .getsetIdcliente = numeroDeCliente
                            .getsetApellidonombreRazonsocial = Me.txtapellidoynombrerazonsocial.Text
                            .getsetDireccion = Me.txtdireccion.Text
                            .getsetNumerodireccion = Me.txtnumerodireccion.Text
                            .getsetLocalidad = Me.cmblocalidad.Text
                            .getsetTelefono = Me.txttelefono.Text
                            .getsetTipodeiva = Me.cmbtipodeconsumidor.Text
                            .getsetCuit = Me.txtcuit.Text
                            .getsetCtacte = Me.cmbctacte.Text
                            .GrabarCliente(cn1)
                            objNumeracion.setNumerodecliente(cn)
                            MsgBox("Los datos fueron grabados exitosamente", MsgBoxStyle.Information, "Ventas")
                        End With
                    Catch err As MySqlException
                        MsgBox("Los datos no fueron grabados [ " & err.Message & " ] [ " & err.Number & " ]", MsgBoxStyle.Critical, "Ventas")
                    End Try
                Case 2 ' actualizar datos


            End Select

    End sub

    El problema que las transacciones como observan estan dentro de las clases, la consulta es si se puede enviar por parametro(que se realice el COMIT dentro de la clase) y en el caso de que hubiese un problema en el ingreso de datos realizar el ROLLBACK desde afuera, el bloque try ctach... end try

    Esto es posible?, me podran ayudar?

    Desde ya muchas gracias

    jueves, 23 de enero de 2014 17:38

Todas las respuestas

  • Hola:

    Lo primero que te puede recomendar es que no concatenes valores en tus consultas, esto es una principal causante de ataques por inyección Sql, después lo que deseas hacer, para el caso de RollBack  necesariamente tienes que establecer el Trycatch para atrapar la excepción, pero no necesariamente tienes que hacerlo en la clase de acceso a datos, podrías crear una clase intermedia que únicamente mande a llamar a los métodos y funciones ubicados en tu clase de acceso a datos y que desntro implemente un try catch para atrapar la excepcion y mandar el rollback.


    Saludos desde Monterrey, Nuevo León, México!!!

    jueves, 23 de enero de 2014 19:45
  • Saludos:

    Lo que yo hago es acumular todos los SQL que deba hacer un procedimiento y renunirlos en una sola transaccion, mediante un array de strings. Algo asi:

    Private Sub Fl_Procesar(ByVal _ArrayProcesos As String())
            Try
               conex = New MySqlConnection(MyConnStr)
                Try
                    conex.Open()
                Catch ex As Exception
                    MsgBox("Network IS NOT Accesible Right Now. Process Abort. ", MsgBoxStyle.Critical, "No Conection Avialable.")
                    Exit Sub
                End Try
    
                MyTrans = conex.BeginTransaction
                For i = 0 To _ArrayProcesos.Count - 1
                    MySqlCadena = CStr(_ArrayProcesos(i))
                    If MySqlCadena.Length > 6 Then
                        MysqlComando = New MySqlCommand(MySqlCadena, conex)
                        With MysqlComando
                            .CommandType = CommandType.Text
                            .CommandTimeout = MySqlTimeOut
                            .Connection = conex
                            .Transaction = MyTrans
                            _FilasAfectadas += .ExecuteNonQuery()
                        End With
                    Else
                        MsgBox("Sentence Empty. Contact IT Department. ", MsgBoxStyle.Critical, "Data Process Empty.")
                        _Resultado = False
                        MyTrans.Rollback()
                    End If
                Next
                MyTrans.Commit()
                _Resultado = True
    
            Catch ex As MySqlException
                MYSQLERROR = ex.Number
                MYSQLMESG = ex.Message
                MyTrans.Rollback()
                _Resultado = False
                Tm_Proceso.Stop()
                MsgBox("Error: " & MYSQLERROR & ". Description : " & MYSQLMESG, MsgBoxStyle.Information, "Data Processing Error.")
            Finally
                conex.Close()
                Me.Close()
            End Try
        End Sub

    Espero ayude.

    JOSE LUIS

    viernes, 24 de enero de 2014 23:51
  • Hola, según lo tienes podrías tener una función (sobrecarga las que tienes) a la que no le pases una transacción, crearla e invocar a otra función que si que acepte la transacción.

    Así podrías usar tus funciones con o sin transacción.

    martes, 28 de enero de 2014 19:05
  • Jose luis, desde ya muchas gracias por tu ayuda, adapte tu codigo a lo que estaba necesitando y me funciono de maravillas, no tenia ni idea que se podia hacer de esa forma, teniendo todo agrupado en un arreglo e irlas ejecutandolas.

    agradecido!!!!!!!

    domingo, 2 de febrero de 2014 15:40