Frage Instanziieren Sie IDataAdapter aus der Instanz von IDbConnection


Ich habe eine Instanz von IDbConnection, die jede Verbindung sein kann, Sql, OleDb usw. Ich möchte einen generischen Wrapper erstellen, so dass ich dem Wrapper einfach eine Verbindung senden und eine Reihe von Methoden zur einfachen Bearbeitung erhalten kann. Ich habe eine Abfrage-Methode, ich möchte es eine DataTable zurückgeben, damit ich es tun kann

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

Das Problem ist, dass ich OleDbAdapter verwenden muss und es für SQL nicht funktionieren würde, ich möchte nicht wirklich "treiberspezifischen" Code schreiben. Gibt es eine Möglichkeit, eine IDataAdapter-Instanz von meinem instanziierten IDbConnection-Objekt zu erhalten? Ich weiß, dass ich einen Befehl erstellen kann

IDbCommand command = _connection.CreateCommand();

Es ist nur logisch zu glauben, dass es einen einfachen Weg gibt, dasselbe mit einem IDataAdapter zu machen.

BEARBEITEN:

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

Nun, nicht genau das, wonach ich gefragt habe, aber eine nette Lösung.


13
2018-05-23 15:49


Ursprung


Antworten:


Hier ist ein grobes Beispiel, wie Sie den Adapter mithilfe von Reflektion erhalten können.

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

7
2018-05-23 17:06



Ich hatte das gleiche Problem. So habe ich es gelöst

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

4
2017-12-13 17:39