Pregunta

¿Cómo se construye una DbConnection basada en un nombre de proveedor ?

Ejemplo de nombre del proveedor s

  • System.Data.SqlClient
  • System.Data.OleDb
  • System.Data.Odbc
  • FirebirdSql.Data.FirebirdClient

tengo cadenas de conexión almacenadas en el archivo web.config de mi servidor IIS:

<connectionStrings>
  <add name="development"
        connectionString="Provider = IBMDA400; Data Source = MY_SYSTEM_NAME; User Id = myUsername; Password = myPassword;" 
        providerName="System.Data.OleDb" />
  <add name="live" 
        connectionString="usd=sa;pwd=password;server=deathstar;" 
        providerName="System.Data.Odbc" />
  <add name="testing" 
        connectionString="usd=sa;pwd=password;server=deathstar;" 
        providerName="System.Data.SqlClient" />
  <add name="offline"
        connectionString="Server=localhost;User=SYSDBA;Password=masterkey;Charser=NONE;Database=c:\data\mydb.fdb"
        providerName="FirebirdSql.Data.FirebirdClient"/>

Puede ver que todos usan diferentes proveedores. Cuando llegue el momento de crear una conexión, tengo que saber qué tipo de DbConnection crear, por ejemplo:

  • SqlConnection
  • OleDbConnection
  • OdbcConnection
  • FbConnection

Las entradas de connectionStrings contienen un proveedorNombre , pero estos no son los nombres de las clases descendientes de DbConnection, pero parecen ser un namespace

¿Cómo hago para construir un DbConnection basado en una cadena providerName ?


public DbConnection GetConnection(String connectionName)
{
    //Get the connectionString infomation
    ConnectionStringSettings cs = 
          ConfigurationManager.ConnectionStrings[connectionName];
    if (cs == null)
       throw new ConfigurationException("Invalid connection name \""+connectionName+"\");

    //Create a connection based on the provider
    DbConnection conn = new DbConnection();

}
¿Fue útil?

Solución

Si sigue esta ruta, creo que querrá usar la clase DbProviderFactories para obtener una DbProviderFactory que puede usar para construir la conexión. No he probado este código, pero creo que funcionará. Es posible que deba buscar el nombre del proveedor utilizando el método GetFactoryClasses en la clase DbProviderFactories y utilizar el InvariantName.

public DbConnection GetConnection(String connectionName)
{
   //Get the connection string info from web.config
   ConnectionStringSettings cs= 
         ConfigurationManager.ConnectionStrings[connectionName];

   //documented to return null if it couldn't be found
   if (cs == null)
      throw new ConfigurationErrorsException("Invalid connection name \""+connectionName+"\"");

   //Get the factory for the given provider (e.g. "System.Data.SqlClient")
   DbProviderFactory factory = 
         DbProviderFactories.GetFactory(cs.ProviderName);

   //Undefined behaviour if GetFactory couldn't find a provider.
   //Defensive test for null factory anyway
   if (factory == null)
      throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");

   //Have the factory give us the right connection object      
   DbConnection conn = factory.CreateConnection();

   //Undefined behaviour if CreateConnection failed
   //Defensive test for null connection anyway
   if (conn == null)
      throw new Exception("Could not obtain connection from factory");

   //Knowing the connection string, open the connection
   conn.ConnectionString = cs.ConnectionString;
   conn.Open()

   return conn;
}

Otros consejos

Consulte este blog de Hanselman para agregar tipos de compilación personalizados para diferentes nombres de cadenas de conexión , parece que puede ajustarse a lo que desea lograr de una manera diferente que usar los tipos de proveedor.

Si el nombre del proveedor para el nombre de conexión particular (dev, test, prod) nunca cambia, ¿por qué no puede cambiar el parámetro de nombre de conexión para su método y establecer la instancia del nombre de proveedor de esa manera?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top