2012-05-23 14 views
13

Tengo una instancia de IDbConnection, que puede ser cualquier conexión, Sql, OleDb, etc. Quiero hacer un contenedor genérico para poder enviar una conexión al contenedor y obtener un conjunto agradable de métodos para una fácil manipulación. tengo un método de consulta, quiero que vuelva un DataTable, por lo que se puede hacerCrear una instancia de IDataAdapter de la instancia de IDbConnection

IDataAdapter adapter = new OleDbDataAdapter(); 
adapter.SelectCommand = myCommand; 
DataSet ds = new DataSet(); 
adapter.Fill(ds); 

El problema es que tengo que usar OleDbAdapter y que no funcionaría para SQL, yo realmente no quiero escriba el código "específico del conductor". ¿Hay alguna manera de obtener una instancia de IDataAdapter de mi objeto IDbConnection instanciado? Sé que puedo crear un comando haciendo

IDbCommand command = _connection.CreateCommand(); 

Es lógico pensar que debe haber alguna manera fácil de hacer lo mismo con un IDataAdapter.

EDIT:

using (var reader = command.ExecuteReader()) 
{ 
    var dataTable = new DataTable(); 
    dataTable.Load(reader); 
} 

Bueno, no exactamente lo que pedí, pero una buena solución.

+1

Cuando escribe el código ADO.Net genérico, en algún momento tendrá los métodos de Fábrica que necesitan ver la propiedad del Proveedor de la cadena de conexión. Si tiene esa pieza, puede usar [DbProviderFactory.CreateDataAdapter] (http://msdn.microsoft.com/en-us/library/system.data.common.dbproviderfactory.createdataadapter.aspx) – mdisibio

+0

+1 para compartir la solución con IDataReader. Tenemos un marco personalizado que se utiliza para manejar conexiones de bases de datos, transacciones, etc., pero (aún) no admite adaptadores de datos. Al usar IDataReader, sin embargo, podemos usar ese marco sin tener que extenderlo/modificarlo. –

+0

Me tomé la libertad de editar su pregunta para agregar la declaración 'using' que [cierra automáticamente el lector] (http://stackoverflow.com/a/2157331/808151). –

Respuesta

7

Aquí hay un ejemplo aproximado de cómo podría obtener el adaptador utilizando la reflexión.

IDataAdapter GetAdapter(IDbConnection connection) { 
    var assembly = connection.GetType().Assembly; 
    var @namespace = connection.GetType().Namespace;  

    // Assumes the factory is in the same namespace 
    var factoryType = assembly.GetTypes() 
         .Where (x => x.Namespace == @namespace) 
         .Where (x => x.IsSubclassOf(typeof(DbProviderFactory))) 
         .Single(); 

    // SqlClientFactory and OleDbFactory both have an Instance field. 
    var instanceFieldInfo = factoryType.GetField("Instance", BindingFlags.Static | BindingFlags.Public); 
    var factory = (DbProviderFactory) instanceFieldInfo.GetValue(null); 

    return factory.CreateDataAdapter(); 
} 
4

Tuve el mismo problema. Así es como lo resolví

private DataSet executeDataQuery(string query, string connection, string provider, out Exception ex) { 
     DataSet ds = new DataSet(); 
     ex = null; 
     DbProviderFactory dbFactory = DbProviderFactories.GetFactory(provider); 
     IDbConnection dbConnection = dbFactory.CreateConnection(); 
     dbConnection.ConnectionString = connection; 
     using (dbConnection) { 
      try { 
       IDbDataAdapter dbAdapter = dbFactory.CreateDataAdapter(); 
       IDbCommand dbCommand = dbConnection.CreateCommand(); 
       dbCommand.CommandText = query; 
       dbCommand.CommandType = CommandType.Text; 
       dbAdapter.SelectCommand = dbCommand; 
       dbAdapter.Fill(ds); 
      } 
      catch (Exception exc) { 
       ex = exc; 
      } 
      finally { 
       if (dbConnection.State == ConnectionState.Open) { 
        dbConnection.Close(); 
       } 
      } 
     } 
     return ds; 
    } 
+0

debe colocar el uso alrededor de IDbConnection dbConnection = dbFactory.CreateConnection(); – BlackICE

Cuestiones relacionadas