【问题标题】:Instantiate IDataAdapter from instance of IDbConnection从 IDbConnection 实例实例化 IDataAdapter
【发布时间】:2015-02-26 15:56:09
【问题描述】:

我有一个IDbConnection的实例,可以是任何连接,Sql,OleDb等。 我想制作一个通用包装器,这样我就可以向包装器发送一个连接并获得一组很好的方法以便于操作。 我有一个 Query 方法,我希望它返回一个 DataTable,所以我可以这样做

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

问题是我必须使用 OleDbAdapter 并且它不适用于 SQL,我真的不想编写“驱动程序特定”代码。 有没有办法从我实例化的 IDbConnection 对象中获取 IDataAdapter 实例?我知道我可以创建一个命令来做

IDbCommand command = _connection.CreateCommand();

认为必须有一些简单的方法来使用 IDataAdapter 来做同样的事情是合乎逻辑的。

编辑:

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

嗯,不完全是我要求的,但一个不错的解决方案。

【问题讨论】:

  • 当您编写通用 ADO.Net 代码时,有时您将拥有需要查看连接字符串的 Provider 属性的工厂方法。如果你有那块,你可以使用DbProviderFactory.CreateDataAdapter
  • +1 用于与 IDataReader 共享解决方案。我们有一个自定义框架,用于处理数据库连接、事务等,但它(尚)不支持数据适配器。然而,通过使用 IDataReader,我们可以使用该框架而无需扩展/修改它。
  • 我冒昧地编辑了您的问题,添加了 using 声明 automatically closes the reader

标签: c#


【解决方案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;
        }
    

    【讨论】:

    • 你应该把 using 放在 IDbConnection dbConnection = dbFactory.CreateConnection();
    • 这里有什么提供者
    • @TanmayNehete 在您的连接字符串配置中,您拥有连接和提供者名称。提供者变量必须具有连接字符串的提供者名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2011-03-07
    相关资源
    最近更新 更多