Как создать DbDataAdapter с учетом DbCommand или DbConnection?

Я хочу создать уровень доступа к данным, который работает с любым поставщиком данных.

Я знаю, что можно создать DbCommand с помощью метода factory, доступного в соединении.

objDbCon.CreateCommand();  

Однако я не мог найти ничего для создания DbDataAdapter. Это ошибка в ADO.NET или что?

Ответы

Ответ 1

DbProviderFactory.CreateDataAdapter *

Также вы можете получить все зарегистрированные DbProviders через DbProviderFactories класс.

* Я думаю, что это неправильное место для этого метода.

Ответ 2

Как и для .NET 4.5, при написании независимого от поставщика кода теперь вы можете использовать перегрузку DbProviderFactories.GetFactory, которая принимает DbConnection, чтобы получить правильный провайдер factory, из которого вы можете создать адаптер данных.

Пример:

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

Кажется, что кто-то из команды ADO.NET прочитал комментарий Яна Бойда к его ответу...:)

Ответ 3

Хотя на это хорошо ответил Сергей, мне потребовалось немного времени, чтобы перевести его на собственные нужды. Таким образом, я понял, что если у вас есть DbConnection, но знаете, что вы используете SqlClient под капотом, ваш код будет выглядеть примерно так:

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

Ответ 4

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

Ответ 5

Учитывая, что вы не знаете тип соединения, которое вам дано,.NET не дает хорошего способа решить проблему. Здесь мы используем:

/// <summary>
/// Construct a DataAdapater based on the type of DbConnection passed.
/// You can call connection.CreateCommand() to create a DbCommand object,
/// but there 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 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;
}

Ответ 6

Вы можете использовать другой способ для получения данных в DataTable без DbDataAdapter.

Вот мой код

                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;