Acceso a datos en .NET Conexión genérica para cualquier motor de base datos
Cuando trabajamos con ADO.NET y queremos realizar una conexión con una base de datos, debemos dar una serie de pasos:
En primer lugar determinar que proveedor vamos a usar, después y según que proveedor utilizar las clases correspondientes, Connection, Command, DataReader y Parameter un ejemplo
En el caso que este disponible un proveedor puntual para una fuente de datos, podemos usar OleDb, y si no esta disponible en está, podemos usar Odbc:
La solución que propongo es Usar las clases de ADO.NET que están en el espacio de nombres System.Data.Common
Para ello necesito dar los siguientes pasos:
Localizar y establecer el proveedor que queremos usar. Para este trabajo, usaremos la clase [DBProviderFactories] que nos servirá para dos cosas: por una parte para enumerar (listar) los proveedores disponibles, y por otra para crear un objeto DbProviderFactory a partir del cual crearemos el resto de los objetos que necesitamos (Connection, Command, DataReader, etc)
El objeto DbProviderFactory es genérico pero sus método permiten crear objetos de la clase adecuada para conectar con el origen de datos, definir comandos, adaptadores de datos, etc. Estos métodos ( que vamos a utilizar) son:
En segundo lugar tenemos que tener la cadena de conexión con la base de datos. Este sigue siendo un requisito ineludible e imprescindible.
Y en tercer lugar realizar la conexión con la base de datos.
Un Ejemplo
''' <summary> ''' Realizar una consulta SELECT , obtener los datos y ''' devolverlos en un DataSet ''' </summary> ''' <returns> Un objeto [System.Data.DataSet]</returns> Public Shared Function CargarUnDataSet() As System.Data.DataSet '------------------------------------------------------------- ' Nombre invariante del proveedor que se emplea para ' crear la clase factoria que crea las demas clases (genericas - System.Data.Common) ' para establecer una conexion a la base de datos ' corresponde a la columna InvariantName de una tabla que devuelve GetFactoryClasses. ' http://msdn.microsoft.com/es-es/library/system.data.common.dbproviderfactories.getfactoryclasses.aspx '------------------------------------------------------------- Dim NombreInvarianteProveedor As String = "System.Data.OleDb" '------------------------------------------------------------- ' La cadena de conexion ' Vamos a establecer una conexion con la base de datos [Northwind] ' concretamente con la version generada por [Microsoft Office Access 2007] ' la version [Northwind 2007.accdb] '------------------------------------------------------------- Dim CadenaConexion As String = _ "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Joaquin\Documents\Northwind 2007.accdb;Persist Security Info=False" '------------------------------------------------------------- ' Nombre de la tabla de la base de datos [Northwind] que vamos a listar Dim nombreTabla As String = "Clientes" '------------------------------------------------------------- ' la orden Sql para seleccionar todos los datos de la tabla Dim cadenaSelectSql As String = "SELECT * FROM " & nombreTabla '------------------------------------------------------------- '------------------------------------------------------- ' Definir los Objetos del espacio [System.Data.Common] '------------------------------------------------------- ' El Objeto Factoria Generica Dim objetoDbFactoria As Common.DbProviderFactory = Nothing ' Objeto conexion Dim objetoDbConexion As Common.DbConnection = Nothing ' Objeto para Montar la cadena de conexion: Dim objetoConnectionStringBuilder As Common.DbConnectionStringBuilder = Nothing ' Objeto Command Dim objetoCommand As Common.DbCommand = Nothing ' un DataAdapter Dim objetoDataAdapter As Common.DbDataAdapter = Nothing ' un DataSet Dim objetoDataSet As DataSet = Nothing '------------------------------------------------------- Try '-------------------------------------- ' El Objeto Factoria Generica objetoDbFactoria = Common.DbProviderFactories.GetFactory(NombreInvarianteProveedor) '-------------------------------- ' El objeto que comprobara y montara la cadena de conexion: objetoConnectionStringBuilder = objetoDbFactoria.CreateConnectionStringBuilder ' esta linea carga y comprueba que la cadena de conexion sea sintacticamente correcta objetoConnectionStringBuilder.ConnectionString = CadenaConexion '-------------------------------------- ' Obtener una conexion objetoDbConexion = objetoDbFactoria.CreateConnection objetoDbConexion.ConnectionString = objetoConnectionStringBuilder.ConnectionString ' abrir la conexion objetoDbConexion.Open() '-------------------------------------- ' crear comando objetoCommand = objetoDbConexion.CreateCommand objetoCommand.CommandType = CommandType.Text ' SELECT * FROM tb_empresa objetoCommand.CommandText = cadenaSelectSql ' del parametro '-------------------------------------------------- ' Obtenemos el DataAdapter siempre despues de fijar la consulta en Command objetoDataAdapter = objetoDbFactoria.CreateDataAdapter ' Adaptador enlazado a la consulta objetoDataAdapter.SelectCommand = objetoCommand ' Instanciamos el DataSet objetoDataSet = New DataSet ' Llenamos el DataSet con los datos obtenidos de la consulta objetoDataAdapter.Fill(objetoDataSet, nombreTabla) '-------------------------------------------------- ' cerrar la conexion (En Finally) '-------------------------------------------------- ' devolver El DataSet Return objetoDataSet Catch ex As Exception Using SW As New System.IO.StringWriter SW.WriteLine("Error del sistema") SW.WriteLine(ex.Message) SW.WriteLine("Proveedor = " & NombreInvarianteProveedor) SW.WriteLine("Cadena Conexion = " & objetoConnectionStringBuilder.ConnectionString) SW.WriteLine("Interrogacion SQL = " & objetoCommand.CommandText) SW.WriteLine("Nombre de la tabla = " & nombreTabla) SW.Flush() Throw New Exception(SW.ToString, ex) End Using Finally '----- If Not (objetoDbFactoria Is Nothing) Then objetoDbFactoria = Nothing End If '----- If Not (objetoDbConexion Is Nothing) Then ' cerrar siempre la conexion objetoDbConexion.Close() objetoDbConexion.Dispose() ' destruir el objeto conexion local objetoDbConexion = Nothing End If '----- If Not (objetoConnectionStringBuilder Is Nothing) Then objetoConnectionStringBuilder = Nothing End If '----- If Not (objetoCommand Is Nothing) Then objetoCommand.Dispose() objetoCommand = Nothing End If '----- If Not (objetoDataSet Is Nothing) Then objetoDataSet.Dispose() objetoDataSet = Nothing End If '----- If Not (objetoDataAdapter Is Nothing) Then objetoDataAdapter.Dispose() objetoDataAdapter = Nothing End If End Try '---------------------- End Function
En el ejemplo que se muestra a continuación se indica cómo se puede establecer una conexión con una base de datos, concretamente con la base de datos [Northwind 2007.accdb] [Microsoft Office Access 2007], por medio de clases del espacio genérico
El código lo que hace es:
Los datos que se necesitan para establecer la conexión, se cargan en variables internas, de esta forma es más fácil y sencillo el ejemplo. Observa que se definen el proveedor, la cadena de conexión, la tabla que queremos leer de la base de daos y la cadena SQL que ejecutara la selección de datos en el objeto Command.
A continuación se definen los objetos
Después (y ya dentro del bloque TRY),
Ahora que tenemos los datos en el DatSet, podemos mostrarlos en un formulario en un control DataGridView.
El código que se muestra a continuación hace, precisamente, esa trabajo
''' <summary> ''' Muestra un DataSet en un control DataGridView ''' </summary> ''' <param name="controlDataGridView">el control DataGridView que muestra los datos</param> ''' <param name="objDataSet">El Objeto DataSet que contiene los datos</param> ''' <param name="mostrarEnModoLectura"> ''' <para> Valor lógico que indica:</para> ''' <para> TRUE..: Los datos se muestran en modo lectura, no se pueden modificar</para> ''' <para> FALSE.: Los datos se muestran en modo edición, que permite añadir, borrar y/o modificar datos. </para> ''' <para> Valor por defecto = [True], modo lectura</para> ''' </param> Friend Shared Sub MostarEnDataGridView( _ ByRef controlDataGridView As DataGridView, _ ByVal objDataSet As DataSet, _ Optional ByVal mostrarEnModoLectura As Boolean = True) Try '------------------------------------------------------ ' Problema--> evitar el error cuando DataSet = nothing If objDataSet IsNot Nothing Then '------------------------------------------------------ ' mostrarlo en el DataGridView With controlDataGridView ' para que se generen automaticamente las columnas .AutoGenerateColumns = True ' borrar todos los datos del control DataGridView .Columns.Clear() ' Modo virtual NO .VirtualMode = False ' Modo lectura o edicion If mostrarEnModoLectura = True Then ' Solo Lectura de datos .ReadOnly = True ' No se permite al usuario añadir datos .AllowUserToAddRows = False ' no se permite al usuario Borrar datos .AllowUserToDeleteRows = False Else .ReadOnly = False .AllowUserToAddRows = True .AllowUserToDeleteRows = True End If ' enlazar el DataGridView1 con la tabla de datos .DataSource = objDataSet ' proporcionar el nombre de la tabla de datos ' Problema--> evitar el error cuando no hay tablas en el DataSet If objDataSet.Tables.Count > 0 Then .DataMember = objDataSet.Tables.Item(0).TableName End If ' ajustar el ancho de la columna al texto mas largo .AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells) ' Mostrar toda la linea seleccionada .SelectionMode = DataGridViewSelectionMode.RowHeaderSelect ' permitir el redimensionamiento de las columnas .AllowUserToResizeColumns = True ' Mostrar errores .ShowCellErrors = True ' activar estilos visuales .EnableHeadersVisualStyles = True ' alternar colores .RowsDefaultCellStyle.BackColor = Drawing.Color.White .AlternatingRowsDefaultCellStyle.BackColor = Drawing.Color.AliceBlue End With End If Catch ex As Exception Throw End Try End Sub
Lo que falta es crear un formulario que realice estas dos operaciones para ello en tu Visual Estudio, añade un nuevo formulario, y ponle un control [DataWGridView]. Añade un botón (llamado Prueba) y en su evento clic escribe el siguiente código
Dim objDataSet As DataSet = Nothing objDataSet = CargarUnDataSet MostarEnDataGridView(DataGridView1, objDataSet, True)
Esta forma de trabajar permite escribir código independientemente del proveedor que vayamos a utilizar, si observa atentamente, todas las clases que se generan, dependen del objeto [DbProviderFactory] Por lo que si cambiamos el valor del [Nombre invariante del proveedor], cambiaremos de forma automática en todo nuestro código el motor de Base de datos empleado. Es decir, con un simple cambio de una línea de código, podemos cambiar de un proveedor Odbc a un proveedor SQL Server.
Como puede suponer esto no es exactamente cierto, porque las parejas Claves-Valor de la cadena de conexión no son estándar para todos los proveedores, pero después de realizar este segundo cambio (si es necesario), el código funcionara perfectamente bien sin necesidad de realizar ningún otro cambio
Vale... Pero... ¿Es realmente necesario todo esto? Pues, la verdad es que con el paso del tiempo, las aplicaciones van creciendo, los sistemas van mejorando, y es, (relativamente) frecuente que haya que adaptar toda una aplicación a otro gestor de base de datos al que la empresa ha migrado, por lo que no es ninguna tontería escribir nuestro código con estas clases por tres razones.
![]() |
|
© 1997 - - La Güeb de Joaquín | |||||
Joaquin Medina Serrano
|
|||||
|