none
Clase para Conectarse a Cualquier Origen de Datos RRS feed

  • Pregunta

  • Buenas Tardes estimados Todos.

    Poco interactuo en este foro, pero se que hay muchas personas con mucha experiencia, y es por eso que reccuro aqui solo cuando ya no encuentro la solucion.

    Estoy haciendo una aplicacion, ejemplo, con la que pretendo enseñar algo de programacion, a unos amigos que no dominan el visual basic . Para esto estoy utilizando Visual basic .net 2013, y estoy accediendo a una base de datos SqLite, pero en el transcurso del desarrollo, me ha surgido la pregunta.

    Que pasa si en vez de conectarme a SqLite, quisiera hacerlo a Acces, o Mysql, Sql Server o Postgre-Sql?

    Debo crear una capa de acceso a datos para cada tipo de base de datos que se me ocurra conectarme?.

    Nota: estoy trabajando en 3 capas.

    Existe alguna forma que yo pueda por parametros indicarle al sistema que tipo de base de datos voy a utilizar, y mediante esta asignacion realizar los respectivos procesos de manipulacion de datos?

    Agradecere si me indican donde puedo documentarme sobre este tema.

    Saludos.

    jueves, 7 de septiembre de 2017 20:16

Respuestas

  • Hola

    Si existe la manera de conectarse a diferentes base de datos sin que afecte la implementación de tu código que persiste contra tu base de datos.

    Revisa este enlace DbProviderFactory

    Implementación

    Public Class clsConexionAD
    
        Private Shared nCon As String
        Friend Shared providerName As String
    
        Public Shared Function GetConexion() As String
            Try
                Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
                Dim cs As ConnectionStringSettings = config.ConnectionStrings.ConnectionStrings("default")
    
                If (cs Is Nothing) Then Throw New ArgumentNullException("nameConnectionString", "El nombre de la cadena de conexión no existe" _
                    & " en el archivo de configuración de la aplicación.")
    
                nCon = cs.ConnectionString
                If (nCon = String.Empty) Then Throw New ArgumentNullException("nameConnectionString", "No existe la cadena de conexion en el valor" _
                        & " con nombre especificado.")
                'nCon = String.Empty
    
                clsConexionAD.providerName = cs.ProviderName
                If (clsConexionAD.providerName = String.Empty) Then Throw New ArgumentNullException("nameConnectionString", "El proveedor .net especificado" _
                    & " actualmente no se encuentra soportado.")
                Return String.Empty
    
                'Catch ex As Exception
            Catch ex As ArgumentException
                MsgBox(ex.ToString)
                Return ex.Message
                'Throw ex
                nCon = ""
            End Try
        End Function
        
        
        Public Shared Function Conectar() As DbConnection
            Dim cnMDB As DbConnection = Nothing
            If nCon = "" Then GetConexion()
            If nCon <> "" Then
                Try
                    Dim factory As DbProviderFactory = DbProviderFactories.GetFactory(clsConexionAD.providerName)
    
                    cnMDB = factory.CreateConnection
                    cnMDB.ConnectionString = nCon
                    '& " ;User ID=sa;Password=lim@1"
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            End If
            Return cnMDB
        End Function
    
        Friend Shared Function GetFactory() As DbProviderFactory
            'Creamos la factoria
            Return DbProviderFactories.GetFactory(clsConexionAD.providerName)
        End Function
    
    
        Public Shared Function AddPrefijoParametro(ByVal parameterName As String) As String
    
            If (providerName = "System.Data.SqlClient") Then
                ' Para el proveedor de datos de SQL server.
                Return "@" & parameterName
            ElseIf (providerName = "System.Data.OleDb") Then
                ' Para proveedores de datos Access.
                Return "?" & parameterName
            Else
                ' Para los proveedores que no usan un prefijo como Mysql y PosgreSql
                Return parameterName
    
            End If
    
        End Function
    
    End Class
     

    Ejemplo de uso contra base de datos SQL Server

    Public Shared Function AddCliente(ByVal cli As E.clsClienteE) As String
            Try
                Using cn As DbConnection = clsConexionAD.Conectar
                    cn.Open()
                    Using cmd As DbCommand = cn.CreateCommand
                        cmd.CommandText = "xspAddCliente"
                        cmd.CommandType = CommandType.StoredProcedure
    
                        With cmd.Parameters
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("idCliente"), DbType.Int32, cli.IdCliente))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("identificacion"), DbType.AnsiString, cli.Identificacion, 13))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("razonSocial"), DbType.AnsiString, cli.RazonSocial, 80))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("nombreComercial"), DbType.AnsiString, cli.NombreComercial, 60))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("ciudad"), DbType.AnsiString, cli.Ciudad, 40))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("direccion"), DbType.AnsiString, cli.Direccion, 100))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("telefono"), DbType.AnsiString, cli.Telefono, 9))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("celular"), DbType.AnsiString, cli.Celular, 9))
                        End With
                        cmd.ExecuteNonQuery()
                        Return String.Empty
                    End Using
                End Using
            Catch ex As Exception
                MsgBox(ex.ToString)
                Return ex.Message
            End Try
        End Function

    Saludos.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 7 de septiembre de 2017 20:51
  • Hola:

    Que pasa si en vez de conectarme a SqLite, quisiera hacerlo a Acces, o Mysql, Sql Server o Postgre-Sql?

     Hasta ahora de forma directa usando los objetos de ADO.Net, la unica forma que conozco y la que ya te han recomendado en las respuestas anteriores es, el uso de las Fabricas de Datos, el cual resulta agradable para consultas simples como SELECT * FROM, UPDATE, INSERT "planos", pero estos temas se complican cuando las consultas requieren funciones propias de cada motor, que como ya sabras Access no tiene las mismas funciones ni capacidades con las que cuenta SqlServer, mismo caso para el resto de Motores mencionados, entonces ¿a que te llevan y orillan el uso de Factorias? a que tengas que escribir esas consultas complejas adecuadas al motor de base de datos que decidas usar, entonces ¿le vez alguna diferencia a crear una capa especializada a cada motor?

    Debo crear una capa de acceso a datos para cada tipo de base de datos que se me ocurra conectarme?.

     Si vas encaminado a cambiar de motor de base de datos de un momento a otro, entonces si, mi recomendacion es que crees una capa de datos por cada motor que sepas que se utilizara, pero ojo, para temas didacticos y para fines meramente culturales creo que es bueno tocar el tema, pero en un mundo real, de operaciones constantes veo poco factible que una empresa seria, decida cambiar de Motor de base de datos a diestra y siniestra, simplemente no le veo sentido, los grandes almacens de datos Teradata, SqlServer, Oracle rara vez seran cambiados, ya que eso implicaria altos costos y cuando esto ocurra, creeme que ya existieron analices de impactos previos.


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

    • Marcado como respuesta Aquim Chinchilla viernes, 8 de septiembre de 2017 17:24
    jueves, 7 de septiembre de 2017 22:34

Todas las respuestas

  • Hola

    Si existe la manera de conectarse a diferentes base de datos sin que afecte la implementación de tu código que persiste contra tu base de datos.

    Revisa este enlace DbProviderFactory

    Implementación

    Public Class clsConexionAD
    
        Private Shared nCon As String
        Friend Shared providerName As String
    
        Public Shared Function GetConexion() As String
            Try
                Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
                Dim cs As ConnectionStringSettings = config.ConnectionStrings.ConnectionStrings("default")
    
                If (cs Is Nothing) Then Throw New ArgumentNullException("nameConnectionString", "El nombre de la cadena de conexión no existe" _
                    & " en el archivo de configuración de la aplicación.")
    
                nCon = cs.ConnectionString
                If (nCon = String.Empty) Then Throw New ArgumentNullException("nameConnectionString", "No existe la cadena de conexion en el valor" _
                        & " con nombre especificado.")
                'nCon = String.Empty
    
                clsConexionAD.providerName = cs.ProviderName
                If (clsConexionAD.providerName = String.Empty) Then Throw New ArgumentNullException("nameConnectionString", "El proveedor .net especificado" _
                    & " actualmente no se encuentra soportado.")
                Return String.Empty
    
                'Catch ex As Exception
            Catch ex As ArgumentException
                MsgBox(ex.ToString)
                Return ex.Message
                'Throw ex
                nCon = ""
            End Try
        End Function
        
        
        Public Shared Function Conectar() As DbConnection
            Dim cnMDB As DbConnection = Nothing
            If nCon = "" Then GetConexion()
            If nCon <> "" Then
                Try
                    Dim factory As DbProviderFactory = DbProviderFactories.GetFactory(clsConexionAD.providerName)
    
                    cnMDB = factory.CreateConnection
                    cnMDB.ConnectionString = nCon
                    '& " ;User ID=sa;Password=lim@1"
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            End If
            Return cnMDB
        End Function
    
        Friend Shared Function GetFactory() As DbProviderFactory
            'Creamos la factoria
            Return DbProviderFactories.GetFactory(clsConexionAD.providerName)
        End Function
    
    
        Public Shared Function AddPrefijoParametro(ByVal parameterName As String) As String
    
            If (providerName = "System.Data.SqlClient") Then
                ' Para el proveedor de datos de SQL server.
                Return "@" & parameterName
            ElseIf (providerName = "System.Data.OleDb") Then
                ' Para proveedores de datos Access.
                Return "?" & parameterName
            Else
                ' Para los proveedores que no usan un prefijo como Mysql y PosgreSql
                Return parameterName
    
            End If
    
        End Function
    
    End Class
     

    Ejemplo de uso contra base de datos SQL Server

    Public Shared Function AddCliente(ByVal cli As E.clsClienteE) As String
            Try
                Using cn As DbConnection = clsConexionAD.Conectar
                    cn.Open()
                    Using cmd As DbCommand = cn.CreateCommand
                        cmd.CommandText = "xspAddCliente"
                        cmd.CommandType = CommandType.StoredProcedure
    
                        With cmd.Parameters
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("idCliente"), DbType.Int32, cli.IdCliente))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("identificacion"), DbType.AnsiString, cli.Identificacion, 13))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("razonSocial"), DbType.AnsiString, cli.RazonSocial, 80))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("nombreComercial"), DbType.AnsiString, cli.NombreComercial, 60))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("ciudad"), DbType.AnsiString, cli.Ciudad, 40))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("direccion"), DbType.AnsiString, cli.Direccion, 100))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("telefono"), DbType.AnsiString, cli.Telefono, 9))
                            .Add(CreateParameter(clsConexionAD.AddPrefijoParametro("celular"), DbType.AnsiString, cli.Celular, 9))
                        End With
                        cmd.ExecuteNonQuery()
                        Return String.Empty
                    End Using
                End Using
            Catch ex As Exception
                MsgBox(ex.ToString)
                Return ex.Message
            End Try
        End Function

    Saludos.


    Pedro Ávila
    "El hombre sabio querrá estar siempre con quien sea mejor que él."
    Lima - Perú

    jueves, 7 de septiembre de 2017 20:51
  • Si es posible, la idea es crear objetos sin tener que especificar el tipo exacto de la instancia sino a través de interfaces (podría ser también a través de clases abstractas) que provee ADO .Net y que definen el marco de la fábrica, de hecho esto que explico se sustenta en el patrón The Factory Pattern

    Utilización de Data Providers (DbProviderFactories)

    Quizá también te sirva ir aprendiendo la manera de crear servicios de acceso a datos mediante el patrón Repository Getting Started With Repository Pattern Using C#


    Nuestra profesión exige tener pasión por resolver problemas de una manera óptima y eficiente.
    jueves, 7 de septiembre de 2017 22:11
  • Hola:

    Que pasa si en vez de conectarme a SqLite, quisiera hacerlo a Acces, o Mysql, Sql Server o Postgre-Sql?

     Hasta ahora de forma directa usando los objetos de ADO.Net, la unica forma que conozco y la que ya te han recomendado en las respuestas anteriores es, el uso de las Fabricas de Datos, el cual resulta agradable para consultas simples como SELECT * FROM, UPDATE, INSERT "planos", pero estos temas se complican cuando las consultas requieren funciones propias de cada motor, que como ya sabras Access no tiene las mismas funciones ni capacidades con las que cuenta SqlServer, mismo caso para el resto de Motores mencionados, entonces ¿a que te llevan y orillan el uso de Factorias? a que tengas que escribir esas consultas complejas adecuadas al motor de base de datos que decidas usar, entonces ¿le vez alguna diferencia a crear una capa especializada a cada motor?

    Debo crear una capa de acceso a datos para cada tipo de base de datos que se me ocurra conectarme?.

     Si vas encaminado a cambiar de motor de base de datos de un momento a otro, entonces si, mi recomendacion es que crees una capa de datos por cada motor que sepas que se utilizara, pero ojo, para temas didacticos y para fines meramente culturales creo que es bueno tocar el tema, pero en un mundo real, de operaciones constantes veo poco factible que una empresa seria, decida cambiar de Motor de base de datos a diestra y siniestra, simplemente no le veo sentido, los grandes almacens de datos Teradata, SqlServer, Oracle rara vez seran cambiados, ya que eso implicaria altos costos y cuando esto ocurra, creeme que ya existieron analices de impactos previos.


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

    • Marcado como respuesta Aquim Chinchilla viernes, 8 de septiembre de 2017 17:24
    jueves, 7 de septiembre de 2017 22:34
  • Efectivamente tenes toda la razon, las empresas Serias utilizan un solo tipo Data Provider, pero la duda me surgio que estoy desarrollando una app muy funcional usando Sqlite, y queria utilizar el codigo solo para no tener que programar nuevamente para MySql u otros, pero tenes toda la razon, para una aplicacion responsable es mejor desarrollar para un proveedor especifico.

    Gracias por sus repuestas.

    viernes, 8 de septiembre de 2017 17:29
  • Santos cielo, hace mucho que no acudia a este foro, pido mil disculpas por contestar hasta hoy.
    Con relacion a mi pregunta el asunto no es por cambiar de bases de datos, sino que: yo como desarrollador pueda decir, tengo un sistema que puedes usarlo tanto con Oracle, como con Acces, Mysql, MariaDB, PostgreSql, de esa forma, si me encuentro un cliente con posibilidades de que compre Sql Server, pues le funcione mi aplicacion, y si encuentro a otro que diga; hombre, el coste de implementar ese sistema es muy elevado, mejor usemos SqLITE, o MySql, O mariaDb que son gratuitos.
    De esa forma no deba yo de volver a compilar para ese cliente.
    Entiendo la repuesta que me distes, pero me referia mas a este tema que al de que un cliente cambie constantemente de motores de base de datos.

    Saludos, y muchas gracias.

    martes, 19 de marzo de 2019 19:28