Активировать IDataAdapter из экземпляра IDbConnection
У меня есть экземпляр IDbConnection, который может быть любым соединением, Sql, OleDb и т.д.
Я хочу создать общую оболочку, чтобы я мог просто отправить оболочку на соединение и получить хороший набор методов для легкого манипулирования.
У меня есть метод запроса, я хочу, чтобы он возвращал DataTable, поэтому я могу сделать
IDataAdapter adapter = new OleDbDataAdapter();
adapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
adapter.Fill(ds);
Проблема в том, что я должен использовать OleDbAdapter, и он не будет работать для SQL, я действительно не хочу писать "специфичный для драйвера" код.
Есть ли способ получить экземпляр IDataAdapter из моего экземпляра объекта IDbConnection? Я знаю, что могу создать команду, выполняющую
IDbCommand command = _connection.CreateCommand();
Логично думать, что должен быть какой-то простой способ сделать то же самое с IDataAdapter.
EDIT:
using (var reader = command.ExecuteReader())
{
var dataTable = new DataTable();
dataTable.Load(reader);
}
Ну, не совсем то, что я просил, но хорошее решение.
Ответы
Ответ 1
Вот приблизительный пример того, как вы могли бы получить адаптер, используя отражение.
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();
}
Ответ 2
У меня была та же проблема. Вот как я его решил
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;
}