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
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.