Colabora .NET

Crear clases y colecciones automáticamente desde MySQL

Como crear clases, colecciones y stored procedures automáticamente conectándose a Mysql y .NET, acelera el desarrollo

 

Fecha: 27/Ago/2006 (24 agosto 2006)
Autor: Omar Alejandro Jonguitud Zamora [email protected]

 


Introducción

Muchas veces, cuando desarrollo, muy en particular, prefiero invertir un poco de tiempo en cosas que me ahorren un mucho de tiempo en el futuro. Como mis aplicaciones casi siempre se llevan de piquete en el ombligo con las bases de datos, mucho de mi tiempo se va en estar creando los procedimientos y las clases que se comunican con esas bases de datos. Además, soy un fiel seguidor de la reutilización de código; por tanto, eso de escribir en cada aplicación/pagina de .net los controles y código para conectarme a una bd (dataadapter, dataset, commands, etc etc) se me hace un poco grotesco. En mi muy humilde opinión, es mejor diseñar clases reutilizables y apoyarse en estos objetos cuando convenga. Así que, crear clases y colecciones + procedimientos de la BD es simplemente muy costoso en tiempo.

 

El código:

Pues si, debido a mis problemas existenciales, me generé una aplicación que se conecta a mysql y me crea mis clases y mis colecciones basados en las tablas de la base de datos que escoja :p. Como es esto. Primero, pues hay que entender como esta formada una clase y una colección; pero, eso es harina de otro costal, aquí te explico las cosas que hice para lograr formar “esa estructura”. Los detalles de cómo se va armando tomando en cuenta llaves primarias y esas artes oscuras lo puedes checar en la colección CMiembrosMySQL.

La pantalla que diseñe se ve así:
Imagen de la aplicacion

El funcionamiento básicamente sería:

  1. Esto obviamente necesitara un servidor de mysql activo, das los datos y pinchas conectar.
  2. Una vez que te conectaste, escoges las tabla en Consulta tabla.
  3. Te generas la clase (esto esta hecho para generar VB.NET, si quieres una versión en C# nada más edita el código de GeneraClase() hehe)
  4. Una vez creada la clase, puedes generarte los Stored procedures y LISTOOOOOOOOOO
Ahora, a desmenuzar esto: Primero, para manejar nuestros datos en la aplicación, usamos unas variables:
#Region "Variables"
    'Esta es mi conexion mysql
    Private objConexion As CConexionMySQL
    Private ds As DataSet
    'Aqui guardo los campos de la bd, 
    'y también guardo el nombre de la propiedad publica de la clase
    Private dtCampos As DataTable
    'Esta va a ser la colección que tendrá todos los elemntos para crear:
    '1) La clase
    '2) La coleccion
    '3) Los stored procedures
    '   (NOTA: esto brinda un stored procedure básico de guardado/Editado y lectura)
    '   Las personalizaciones de lectura con subcatalogos
    '   o cosas similares, deberás programarla tu hehe
    Private objMiembros As New CMiembrosMySQL
#End Region

Para conectarnos a la BD necesitamos algo como esto:

'Esto me da una conexion a la bd
Private Sub btnConectar_Click( _
	ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles btnConectar.Click
    Dim bConectado As Boolean
    'Esta es una clase que hice para hacer conexiones a base de datos,
    'en este caso es de mysql
    objConexion = New CConexionMySQL(txtUser.Text, _
    txtPassword.Text, _
    txtDB.Text, _
    txtServer.Text)

    'Aqui simplemente nos conectamos
    bConectado = objConexion.ConnectToDatabase()

    If bConectado Then
        If ds Is Nothing Then ds = New DataSet

        'Carga las tablas disponibles del servidor en el dataset
        'Esto lo hace con instrucciones de mysql
        If objConexion.Consulta("show tables", "tablas", ds) Then
            With cmbTablas
                .DataSource = ds.Tables("tablas")
                .ValueMember = ds.Tables("tablas").Columns(0).Caption
                .DisplayMember = .ValueMember
            End With
            btnConsultaTabla.Enabled = True
        Else
            btnConsultaTabla.Enabled = False
        End If
    Else
        MessageBox.Show("No se pudo conectar con la base de datos", "Avner", _
		MessageBoxButtons.OK)
    End If
End Sub

Para hacer la transformación de tipos de mysql a vb.net necesitamos una interface, esta función nos sirve (editala para agregar todos los tipos y su equivalencia, solo puse los más comunes para mí)

'Esta funcion busca el tipo equivalente de vb.net para el tipo almacenado en mysql
Private Sub TiposVB(ByRef objMiembro As CMiembroMySQL, ByRef strPrefijo As String)
    'Modificar esta seccion para incluir los tipos que se utilizarán en MySQL
    'Esto con el fin de crear el tipo de dato en la clase que pueda almacenar 
    'la información, el prefijo solo es para armar la clase

    'NOTA: si tienes campos BLOB o alguno que no veas en la lista, solo agregalo en otro
    '       case para que asignes el tipo de dato correcto en vb.net

    Dim arr1(), arr2(), arr3() As String
    Dim strTipo As String

    Try
        'Con esto separamos el tipo de la precisión
        arr1 = Split(objMiembro.TipoBD, "(")

        'invariablemente, en el elemento cero, esta el tipo, halla o no
        'tamaño y precision
        objMiembro.TipoBD = arr1(0).ToUpper()

        'De acuerdo al tipo de mysql, sacamos el tipo de VB
        'Recuerda, agregale los tipos que consideres necesarios
        Select Case objMiembro.TipoBD
            Case "TINYINT", "SMALLINT", "BIT"
                strTipo = "Short"
                strPrefijo = "s"
            Case "VARCHAR", "CHAR"
                strTipo = "String"
                strPrefijo = "str"
            Case "BOOLEAN"
                strTipo = "Boolean"
                strPrefijo = "bol"
            Case "FLOAT", "DECIMAL", "DOUBLE"
                strTipo = "Decimal"
                strPrefijo = "dec"
            Case "INTEGER", "MEDIUMINT", "INT"
                strTipo = "Integer"
                strPrefijo = "int"
            Case "BIGINT"
                strTipo = "Long"
                strPrefijo = "lng"
            Case "DATETIME", "DATE"
                strTipo = "DateTime"
                strPrefijo = "dt"
            Case Else
                strTipo = "Object"
                strPrefijo = "obj"
        End Select

        objMiembro.Tipo = strTipo
        objMiembro.Prefijo = strPrefijo

        'Si el tamaño del arreglo es 2, quiere decir que hay tamaño y/o precision,
        'nos interesa solo el tamaño (VG puede ser varchar(200), decimal(10,3)
        If arr1.Length = 2 Then
            arr2 = Split(arr1(1), ")")
            'tenemos ya sea el tamaño o el tamaño y precision en el elemento 0,
            'nos interesa solo el tamaño para los stored procedures que piden tipo y tamaño

            arr3 = Split(arr2(0), ",")
            'Ahora, el tamaño esta en la posición 0 de arr3
            objMiembro.Tamano = arr3(0)
        End If

    Catch ex As Exception
        strPrefijo = "obj"
    End Try

End Sub


Después, en la parte que la aplicación consulta la tabla, lo que realmente hace la chamba es esto:

'Si puede leer las columnas de la tabla, entonces las muestra y permite editar el
'nombre de la propiedad que representará la columna, la tabla dtCampos tendrá solo
'los datos que necesitamos (field, property, type, ESPK -nos dice si usamos los campos
'   llave para hacer las selecciones-)
If objConexion.Consulta("SHOW columns from " & Me.cmbTablas.SelectedValue, _
"campos", ds) Then


Esa función “SHOW COLUMNS FROM tabla” es la que trae la estructura de mysql. La función completa la puedes ver en el código de la forma frmCCMySQLSchema, la función responde al evento clic de consulta tabla La siguiente función de la forma, es la que toma los datos de mysql y las propiedades QUE TU TIENES QUE DAR (Es decir, como quieres referir a los elementos de la clase desde tu aplicación, porque los nombres se forman un poco funky, tipo m_str_suc_clave, la propiedad podría ser ClaveSucursal en caso de que eso signifique en la base de datos).


'Aqui es donde realmente se genera nuestra clase y colección
Private Sub btnGenerar_Click_1( _
	ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles btnGenerar.Click

    Dim objMiembro As CMiembroMySQL
    Dim strPrefijo As String = ""
    Dim strClase As String

    Try
        objMiembros = New CMiembrosMySQL
        dtCampos.AcceptChanges()

        For Each drow As DataRow In dtCampos.Rows
            objMiembro = New CMiembroMySQL
            'obtenemos el tipo,
            'se asigna tambien un 'tipo completo' porque:
            '   1) TipoDB tendrá el tipo de la base de datos
            '   2) TipoDBCompleto incluirá el tamaño y la precisión (si aplica)
            '      -- esto nos sirve en los stored procedures
            objMiembro.TipoBD = drow("Type")
            objMiembro.TipoBDCompleto = drow("type")
            'Indicador de si es llave primaria
            objMiembro.EsPK = IIf(drow("key") = "PRI", True, False)

            'Del tipo mysql, saca el tipo VB y asigna el tipo correcto 
            'y tamaño desglosado de mysql
            TiposVB(objMiembro, strPrefijo)

            objMiembro.Propiedad = drow("property")
            objMiembro.NombreCompleto = "m_" & strPrefijo & "_" & drow("property")
            objMiembro.Prefijo = strPrefijo
            'por default pone los datos privados con propiedades publicas,
            ' edita al final si consideras necesario
            objMiembro.Ambito = "private"
            objMiembro.CampoBD = drow("field")

            objMiembros.Agregar(objMiembro)
            objMiembro = Nothing
        Next

        'Los nombres de la clase y la coleccion los proporciona el usuario
        'Para mis estándares XD siempre antepongo a las clases la letra C
        'Asi, mi clase para el catalogo de Cheques, sera CCheque y la coleccion CCheques
        'El programa antepone esta C, entonces los nombres que proporciono son 
        'Cheque y Cheques (que tambien se usa para crear los nombres de los stored procedures)
        objMiembros.NombreClase = txtNombreClase.Text
        objMiembros.NombreColeccion = txtNombreColeccion.Text

        'Aqui se genera la clase tal cual, checate el archivo
        'CCREACLASESMYSQL (clase CMiembrosMysql, funcion genera clase)
        'Ahi esta la verdad absoluta de esto, solamente genera la cadena basado en los datos
        'es algo tedioso y largo pero ahorra mucho tiempo en proyectos que tienes 80 catalogos
        'y al igual que yo tal vez prefieras diseñar tus clases
        ' para reutilizar objetos en diferentes
        'partes de tu programa,

        'LO QUE GENERA ES:
        '1) La clase del objeto individual con
        '   1.1) Una region de datos miembro 
        '    1.2) Una region de propiedades
        '    1.3) Una region de funciones (Lectura, guardado,
        '         si quieres incluir el borrado,
        '         basicamente duplica la lectura pero con un sp diferente)
        '    1.4) El constructor
        '2) La coleccion (para que manejes tus objetos y puedas asignar datagrids y cosas asi
        '    1.1) funciones para manejar la coleccion
        '    1.2) Guardado
        '    1.3) Lectura
        '    1.4) Ordenamiento (comentado, ya que esto hay que personalizarlo)
        '    1.5) Filtrado (comentado, ya que esto hay que personalizarlo)

        strClase = objMiembros.GeneraClase()
        btnGeneraSP.Enabled = True
        rtxtClase.Text = strClase

        Dim sfdGuardar As New System.Windows.Forms.SaveFileDialog
        With sfdGuardar
            .DefaultExt = "vb"
            .Title = "Escoge el archivo para guardar la clase"
            .FileName = objMiembros.NombreColeccion + "." + .DefaultExt

            If .ShowDialog() = DialogResult.OK Then
                rtxtClase.SaveFile(.FileName, _
                RichTextBoxStreamType.PlainText)
            End If
        End With

        btnGeneraSP.Enabled = True
    Catch ex As Exception
        btnGeneraSP.Enabled = False
    End Try

End Sub


Finalmente, te has de estar preguntando ¿Y mis stored procedures que?, hay un botonazo ahí que genera los sp (repito, el armado del stored procedure esta en la colección CMiembrosMySQL del archivo CCreaClasesMySQL.vb

'Este genera los Stored procedures,
'no saben cuanto tiempo de desarrollo me he ahorrado por que
'me genere toda la lista de inserciones, actualizaciones y lectura
'al menos elimino todos los errores de tipear mal el nombre de los campos y cosas asi
Private Sub btnGeneraSP_Click( _
	ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles btnGeneraSP.Click
    If objMiembros Is Nothing Then
        MessageBox.Show("Genere primero la clase", "Atencion", MessageBoxButtons.OK)
        Exit Sub
    End If

    'Aqui se genera la clase tal cual, checate el archivo
    'CCREACLASESMYSQL (clase CMiembrosMysql, funcion GeneraSPs)
    rtxtClase.Text = objMiembros.GeneraSPs()

    Dim sfdGuardar As New System.Windows.Forms.SaveFileDialog
    With sfdGuardar
        .DefaultExt = "sql"
        .Title = "Escoge el archivo para guardar el script"
        .FileName = objMiembros.NombreColeccion + "." + .DefaultExt

        If .ShowDialog() = DialogResult.OK Then
            rtxtClase.SaveFile(.FileName, _
            RichTextBoxStreamType.PlainText)
        End If
    End With

End Sub

NOTA IMPORTANTE:

Necesitas bajarte el driver de MySQL para .NET, lo encuentras en www.mysql.com, lo instalas y lo agregas a las referencias del proyecto


LISTO, ESPERO QUE ESTO LES SIRVA COMO ME HA SERVIDO A MÍ Y SI TIENEN DUDA DE ALGO, ME PREGUNTAN.

Saludos cordiales,
Omar Jonguitud

 


Espacios de nombres usados en el código de este artículo:

MySQL.Data

 


Código de ejemplo (ZIP):

 

Fichero con el código de ejemplo: ojonguitud_coleccionesmysql.zip - 31.7 KB

(MD5 checksum: 43D50613AAC7F6BF5E7FA3C8B869EE9D)

 


ir al índice principal del Guille