2010-08-15 9 views
15

Voglio creare un livello di accesso ai dati che funziona con qualsiasi provider di dati.Come creare un DbDataAdapter dato un DbCommand o DbConnection?

so che è possibile creare una DbCommand utilizzando il metodo factory disponibili sulla connessione.

objDbCon.CreateCommand(); 

Tuttavia, non ho trovato nulla per creare un DbDataAdapter. È un bug in ADO.NET o cosa?

risposta

10

DbProviderFactory.CreateDataAdapter *

Inoltre è possibile ottenere tutte le DbProviders registrati tramite DbProviderFactories classe.

* Penso che questo è un posto sbagliato per questo metodo.

+2

Dato un 'DbCommand' o' DbConnection', come si ottiene il corrispondente 'DbProviderFactory'? –

+0

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

5

Anche se questo è stato risposto bene da Sergey, mi c'è voluto un po 'per tradurlo alle mie esigenze. Quindi la mia comprensione è che se si ha un DbConnection ma sapeva che si stava utilizzando uno SqlClient sotto il cofano il codice sarebbe simile:

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

Dato che non si conosce il tipo di connessione si è data,. NET non offre un buon modo per risolvere il problema. Ecco ciò che usiamo:

/// <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

questo funzionerà ma non penso che sia il modo migliore per farlo :) – Karim

+2

@Karim ho *** amore *** una soluzione migliore. avrei pensato 'connection.CreateAdapater', o' DbProviderFactories.GetFactory (connessione) ',' o DbProviderFactories.GetFactory (typeof (collegamento)) ', o qualcosa di *** ***. –

+0

Si noti che questo sembra essere quello che il team di ADO.NET * ha effettivamente implementato * a partire da .NET 4.5. –

15

A partire dal .NET 4.5, quando si scrive fornitore indipendente del codice, è ora possibile utilizzare il DbProviderFactories.GetFactory overload che accetta un DbConnection per ottenere il corretto fabbrica fornitore da cui è possibile quindi creare un adattatore dati.

Esempio:

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

Sembra che qualcuno del team di ADO.NET leggere Ian Boyd commento sulla sua risposta ... :)

+2

ho solo cercato su google la soluzione a questo problema; un anno dopo. I miei casi hardcoded non gestiscono 'SqlCeConnection' e' SqlCeDataAdapter'. E poiché questo è un codice condiviso, non voglio forzare tutti i client a installare 'SQL Server CE' quando non lo usano nemmeno. Complimenti a te per aver trovato quello che avrebbe dovuto essere necessario in primo luogo! –

+0

È scritto in qualsiasi luogo che ** GetFactory (connessione) ** sta solo lavorando in **. ** netta 4,5 ?, perché [MSDN] (https://msdn.microsoft.com/en-us/library/hh323136 (v = vs.100) .aspx) dice che è supportato in ** 4.0 **, ma nel mio caso non lo è. – mayank

0

È possibile utilizzare un altro modo per ottenere i dati in DataTable senza DbDataAdapter.

Ecco il mio codice

   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; 
} 
Problemi correlati