2010-08-15 12 views
15

Quiero crear una capa de acceso a datos que funcione con cualquier proveedor de datos.¿Cómo crear un DbDataAdapter dado un DbCommand o DbConnection?

Sé que es posible crear un DbCommand utilizando el método de fábrica disponible en la conexión.

objDbCon.CreateCommand(); 

Sin embargo, no pude encontrar nada para crear un DbDataAdapter. ¿Esto es un error en ADO.NET o qué?

Respuesta

10

DbProviderFactory.CreateDataAdapter *

También se puede obtener toda DbProviders registrados a través de DbProviderFactories clase.

* Creo que este es un lugar equivocado para este método.

+2

Dado un '' DbCommand' o DbConnection', ¿cómo se consigue la correspondiente 'DbProviderFactory'? –

+0

@Ian Boyd http://msdn.microsoft.com/en-us/library/hh323136.aspx –

5

Aunque Sergey me contestó bien, me tomó un poco de tiempo traducirlo a mis propias necesidades. Así que mi entendimiento es que si has tenido una DbConnection pero sabía que estaba usando un SqlClient bajo el capó su código sería algo como:

DbDataAdapter da = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateDataAdapter(); 
1

Dado que usted no sabe el tipo de conexión que se le da,. NET no ofrece una buena manera de resolver el problema. Esto es lo que utilizamos:

/// <summary> 
/// Construct a DataAdapater based on the type of DbConnection passed. 
/// You can call connection.CreateCommand() to create a DbCommand object, 
/// but there's no corresponding connection.CreateDataAdapter() method. 
/// </summary> 
/// <param name="connection"></param> 
/// <exception>Throws Exception if the connection is not of a known type.</exception> 
/// <returns></returns> 
public static DbDataAdapter CreateDataAdapter(DbConnection connection) 
{ 
    //Note: Any code is released into the public domain. No attribution required. 

    DbDataAdapter adapter; //we can't construct an adapter directly 
     //So let's run around the block 3 times, before potentially crashing 

    if (connection is System.Data.SqlClient.SqlConnection) 
     adapter = new System.Data.SqlClient.SqlDataAdapter(); 
    else if (connection is System.Data.OleDb.OleDbConnection) 
     adapter = new System.Data.OleDb.OleDbDataAdapter(); 
    else if (connection is System.Data.Odbc.OdbcConnection) 
     adapter = new System.Data.Odbc.OdbcDataAdapter(); 
    else if (connection is System.Data.SqlServerCe.SqlCeConnection) 
     adapter = new System.Data.SqlServerCe.SqlCeDataAdapter(); 
    else if (connection is Oracle.ManagedDataAccess.Client.OracleConnection) 
     adapter = new Oracle.ManagedDataAccess.Client.OracleDataAdapter(); 
    else if (connection is Oracle.DataAccess.Client.OracleConnection) 
     adapter = new Oracle.DataAccess.Client.OracleDataAdapter(); 
    else if (connection is IBM.Data.DB2.DB2Connection) 
     adapter = new IBM.Data.DB2.DB2DataAdapter(); 
    //TODO: Add more DbConnection kinds as they become invented 
    else 
    { 
     throw new Exception("[CreateDataAdapter] Unknown DbConnection type: " + connection.GetType().FullName); 
    } 

    return adapter; 
} 
+1

esto funcionará pero no creo que sea la mejor manera de hacerlo :) – Karim

+2

@Karim tengo *** amor *** una mejor solución. Hubiera pensado 'connection.CreateAdapater', o' DbProviderFactories.GetFactory (connection) ', o' DbProviderFactories.GetFactory (typeof (connection)) ', o *** something ***. –

+0

Tenga en cuenta que esto parece ser lo que el equipo de ADO.NET * realmente implementó * a partir de .NET 4.5. –

15

A partir de .NET 4.5, al escribir proveedor de código independiente, ahora se puede utilizar la sobrecarga de DbProviderFactories.GetFactory que acepta un DbConnection para obtener la fábrica proveedor correcta de la que a continuación, puede crear una adaptador de datos

Ejemplo:

DbDataAdapter CreateDataAdapter(DbConnection connection) 
{ 
    return DbProviderFactories.GetFactory(connection).CreateDataAdapter(); 
} 

Parece que alguien en el equipo de ADO.NET leer comentarios Ian Boyd en su respuesta ... :)

+2

Acabo de buscar en Google la solución a este problema; un año después. Mis casos codificados no manejan 'SqlCeConnection' y' SqlCeDataAdapter'. Y dado que este es código compartido, no quiero forzar a cada cliente a instalar 'SQL Server CE' cuando ni siquiera lo están usando. ¡Felicitaciones a usted por encontrar lo que debería haber sido necesario en primer lugar! –

+0

¿Está escrito donde ** ** GetFactory (conexión) ** solo funciona en ** .net 4.5 ** ?, porque [MSDN] (https://msdn.microsoft.com/en-us/library/hh323136 (v = vs.100) .aspx) dice que es compatible con ** 4.0 **, pero en mi caso no lo es. – mayank

0

Se puede utilizar otra forma de obtener datos en DataTable sin DbDataAdapter.

Aquí está mi código

   DataTable dt = new DataTable(); 
       using (IDataReader dr = com.ExecuteReader()) 
       { 
        if (dr.FieldCount > 0) 
        { 
         for (int i = 0; i < dr.FieldCount; i++) 
         { 
          DataColumn dc = new DataColumn(dr.GetName(i), dr.GetFieldType(i)); 
          dt.Columns.Add(dc); 
         } 
         object[] rowobject = new object[dr.FieldCount]; 
         while (dr.Read()) 
         { 
          dr.GetValues(rowobject); 
          dt.LoadDataRow(rowobject, true); 
         } 
        } 
       } 
       return dt; 
2
private static DbDataAdapter CreateDataAdapter(DbCommand cmd) 
{ 
    DbDataAdapter adapter; 

    /* 
    * DbProviderFactories.GetFactory(DbConnection connection) seams buggy 
    * (.NET Framework too old?) 
    * this is a workaround 
    */ 
    string name_space = cmd.Connection.GetType().Namespace; 
    DbProviderFactory factory = DbProviderFactories.GetFactory(name_space); 
    adapter = factory.CreateDataAdapter(); 
    adapter.SelectCommand = cmd; 
    return adapter; 
} 
Cuestiones relacionadas