Cómo crear una base de datos Microsoft Access mediante reflexión
Por Enrique Martínez Montejo
Última revisión: 17/10/2015
 

La manera más fácil de crear una nueva base de datos Microsoft Access mediante programación es referenciando en nuestro proyecto de Visual Basic .net las bibliotecas clásicas de ADO y ADOX, tal como explico en el artículo Cómo crear una nueva base de datos Microsoft Access. Como podrá observar el lector, se utiliza la interoperabilidad COM para poder utilizar las mencionadas bibliotecas que han sido referenciadas en nuestro proyecto.

Pero tampoco es sumamente necesario referenciar explícitamente en nuestro proyecto biblioteca alguna, porque el propio marco de trabajo de .net pone a nuestra disposición un conjunto de clases para poder acceder y manipular módulos y ensamblados mediante técnicas de reflexión, permitiéndonos recuperar el objeto System.Type de los objetos, incluyendo el objeto Type de cualquier componente COM que se encuentre debidamente registrado en el sistema, como bien puede ser la biblioteca de ADOX.

El conjunto de clases que nos permite tal posibilidad se encuentra dentro del espacio de nombres System.Reflection, a excepción del objeto System.Type, que se encuentra dentro del propio espacio de nombres System, por tanto, lo primero que haremos será importar en nuestro módulo el siguiente espacio de nombres:

Imports System.Reflection

A continuación, crearemos un procedimiento general que será el encargado de crear la base de datos propiamente dicha, mediante llamadas a otras funciones auxiliares más específicas. Para ello, al procedimiento le deberá pasar una cadena de conexión Ole Db adecuada, que incluya la ruta y el nombre de la base de datos que se desea crear, así como los restantes parámetros que estime conveniente.

''' <summary>
''' Crea una nueva base de datos Microsoft Access utilizando la biblioteca ADOX.
''' </summary>
''' <param name="connString">Cadena de conexión Ole Db con la información
''' necesaria para crear la nueva base de datos.</param>
''' <remarks></remarks>

Public Sub CreateDatabaseAccess(connString As String)

    ' La función asume que no existe el archivo de base de datos, y que la
    ' cadena de conexión cumple con los parámetros necesarios, entre ellos,
    ' el parámetro Data Source.
    '

    ' Creamos un objeto Catalog de la biblioteca de ADOX
    '

    Dim ty As Type = Nothing
    Dim cat As Object = CreateObject("ADOX.Catalog", ty)
    If (cat Is Nothing) Then Return

    Dim obj As Object = Nothing

    Try
        ' Generamos una nueva base de datos Microsoft Access.
        '

        Dim param() As Object = {connString}
        obj = ExecuteMethod(cat, ty, "Create", param)

        If (Not obj Is Nothing) Then
            ' Se ha creado con éxito la base de datos
            '
            ' Referenciamos el objeto ADODB.Connection subyacente.
            '

            cat = GetProperty(cat, ty, "ActiveConnection", New Object() {})
   
            ' Cerramos la conexión.
            '

            ExecuteMethod(cat, ty, "Close", Nothing)
        End If

    Finally
        If (Not cat Is Nothing) Then
            ' Disminuimos el contador de referencias y liberamos
            ' la referencia al objeto.

            Runtime.InteropServices.Marshal.FinalReleaseComObject(cat)
            cat = Nothing
        End If

        If (Not obj Is Nothing) Then
            Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
            obj = Nothing
        End If

    End Try

End Sub

La siguiente función auxiliar crea y devuelve una referencia al objeto COM que se haya especificado mediante su ProgId:

''' <summary>
''' Crea y devuelve una referencia al objeto COM especificado.
''' </summary>
''' <param name="progId">Nombre correspondiente al ProgId del objeto COM que se desea obtener.</param>
''' <param name="ty">Se devolverá el tipo asociado al identificador de programa especificado.</param>
''' <returns></returns>
''' <remarks></remarks>

Private Function CreateObject(progId As String, ByRef ty As Type) As Object

    ' Obtener el tipo asociado al identificador de programa (ProgID) especificado.
    '

    ty = Type.GetTypeFromProgID(progId)

    Dim obj As Object = Nothing

    If (Not ty Is Nothing) Then
        ' Crear la instancia del tipo de objeto especificado.
        '
        
obj = Activator.CreateInstance(ty)
    End If

    Return obj

End Function

A continuación, escribiremos una función que se encargará de ejecutar los métodos del objeto especificado, utilizando para ello el método InvokeMember del objeto System.Type adecuado:

''' <summary>
''' Ejecuta un método de instancia público en el objeto especificado.
''' </summary>
''' <param name="app">Instancia del objeto COM cuya método público se desea ejecutar.</param>
''' <param name="ty">El tipo asociado al programa especificado.</param>
''' <param name="methodName">Nombre del método de instancia público que se desea ejecutar.</param>
''' <param name="args">Matriz que contiene los argumentos que se van
''' a pasar al método que se desea ejecutar.</param>
''' <returns></returns>
''' <remarks></remarks>

Private Function ExecuteMethod(app As Object, ty As Type, methodName As String, args As Object()) As Object

    Dim obj As Object = Nothing
       
    If
((Not app Is Nothing) AndAlso (Not ty Is Nothing)) Then

        ' Ejecutar el método especificado.
        '

        obj = ty.InvokeMember(methodName, _
                BindingFlags.Instance Or BindingFlags.Public Or _
                BindingFlags.IgnoreCase Or BindingFlags.InvokeMethod, _
                Nothing, app, args)
    End If

    Return obj

End Function

Y si la anterior función se encarga de ejecutar los métodos de un objeto, ahora construiremos la última función auxiliar para leer el valor de las propiedades del objeto.

''' <summary>
''' Obtiene el valor de la propiedad del objeto COM especificado.
''' </summary>
''' <param name="app">Instancia del objeto COM cuya propiedad se desea leer.</param>
''' <param name="ty">El tipo asociado al programa especificado. </param>
''' <param name="propertyName">Nombre de la propiedad.</param>
''' <param name="args">Matriz que contiene los argumentos que se van a pasar a la propiedad. </param>
''' <returns></returns>
''' <remarks></remarks>

Private Function GetProperty(app As Object, ty As Type, propertyName As String, args As Object()) As Object

    Dim value As Object = Nothing
       
    If
((Not app Is Nothing) AndAlso (Not ty Is Nothing)) Then
        ' Leo el valor de la propiedad pública de instancia especificada.
        '

        value = ty.InvokeMember(propertyName, _
                                BindingFlags.Instance Or BindingFlags.Public Or _
                                BindingFlags.IgnoreCase Or BindingFlags.GetProperty, _
                                Nothing, app, args)
    End If

    Return value

End Function

¡Bueno! Ya sólo queda llamar a la función CreateDatabaseAccess para crear una nueva base de datos Microsoft Access, en el ejemplo, una base de datos con formato de archivo Microsoft Access 2007-2016:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Try
        CreateDatabaseAccess("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Bases\Nuevo1.accdb")
        MessageBox.Show("La base de datos se ha creado satisfactoriamente.")

    Catch ex As Exception
        Dim msg As String = String.Format("No se ha podido crear la base de datos.{0}{0}{1}", Environment.NewLine, _
                            If(ex.InnerException Is Nothing, ex.Message, ex.InnerException.Message))

        MessageBox.Show(msg)

    End Try

End Sub

Como habrá tenido ocasión de comprobar, la reflexión nos proporciona una alternativa para evitar referenciar en tiempo de diseño componentes COM en nuestro proyecto, porque lo que hace es crear dinámicamente los objetos en tiempo de ejecución. Pero por utilizar esta técnica, tenemos que pagar un precio, que consiste en que no podemos utilizar la característica de IntelliSense disponible en el entorno de trabajo de Visual Studio, por tanto, tendremos que conocer con soltura los métodos y propiedades de aquellos objetos con los cuales vamos a trabajar.

 

Otros enlaces de interés:

Cómo crear una nueva base de datos Microsoft Access

Cómo crear una nueva base de datos Microsoft SQL Server

Indice de Ejemplos de ADO .NET


Enrique Martínez Montejo - 2015

NOTA: La información contenida en este artículo, así como el código fuente incluido en el mismo, se proporciona COMO ESTÁ, sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo explicado, recomendado o sugerido en el presente artículo.

NOTE: The information contained in this article and source code included therein, is provided AS IS without warranty of any kind, and confers no rights. You assume any risk to implement, use or run it explained, recommended or suggested in this article.