2009-06-25 39 views
10

¿Cómo se construye una conexión Db basada en un nombre de proveedor ?ASP.NET: cómo crear una conexión desde un web.config ConnectionString?

Muestra nombre del proveedor de 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"/> 

Se puede ver que todos utilizan diferentes proveedores. Cuando llega el momento para mí para crear una conexión, tengo que saber qué tipo de DbConnection para crear, por ejemplo:

  • SqlConnection
  • OleDbConnection
  • OdbcConnection
  • FbConnection

El Las entradas de connectionStrings contienen un providerName, pero estos no son los nombres de las clases descendientes de DbConnection, pero parecen ser un espacio de nombres

¿Cómo puedo convertir construir una conexión Db basada 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(); 

} 

Respuesta

15

Si sigue esta ruta, creo que querrá usar la clase DbProviderFactories para obtener una DbProviderFactory que pueda usar para construir la conexión. No he probado este código, pero creo que funcionará. Es posible que necesite buscar el nombre del proveedor utilizando el método GetFactoryClasses en la clase DbProviderFactories y usar 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; 
} 
+1

Esto es exactamente lo que se necesita. El ingrediente secreto es el "nombre del proveedor" que se usa en algún lugar del sistema, y ​​esa es la colección DbProviderFactories. Cada proveedor se registra con los DbProviderFactories; así es como lo encuentras. –

0

Salida this Hanselman blog en la adición de tipos de generación personalizada para los nombres de diferentes cadenas de conexión, todo apunta a que puede adaptarse a lo que quiere lograr de una manera diferente que el uso de los tipos de proveedores.

+0

No son versiones diferentes. Un sistema tiene que conectarse a varias bases de datos según las circunstancias. –

+1

ahh, he entendido mal el ejemplo. No creo que una aplicación se conecte a Desarrollo, Producción y Pruebas al mismo tiempo. – blu

0

Si el providerName para el nombre de la conexión en particular (dev, test, prod) nunca cambia por qué no puede usted hace un cambio en el parámetro connectionName para su método y configurar la instancia providerName de esa manera?

+0

Porque esa no es esta pregunta. –

+0

Porque de esa manera yace la locura. Cinco años más tarde, un nuevo desarrollador obtiene la tarea de mover la base de datos de prueba de SQL Server a Oracle. Actualizan la cadena de conexión, y falla miserablemente. Las suposiciones ocultas como esta (es decir, la base de datos dev utiliza el proveedor de base de datos X) son una muy buena manera de causar rasgaduras en el camino. – Yuliy

+0

Para ser honesto, no es una buena solución para empezar. Tener su código de producción depende de cambiar dinámicamente los proveedores de bases de datos trae lágrimas mucho antes de tratar de resolver esta cuestión aquí. – Marc

Cuestiones relacionadas