如何在给定 DbCommand 或 DbConnection 的情况下创建 DbDataAdapter?

发布于 2024-09-14 03:04:21 字数 210 浏览 1 评论 0原文

我想创建一个可与任何数据提供者一起使用的数据访问层。

我知道可以使用连接上可用的工厂方法创建 DbCommand

objDbCon.CreateCommand();  

但是,我找不到任何东西来创建DbDataAdapter。这是 ADO.NET 中的错误还是什么?

I want to create a data access layer that works with any data provider.

I know it's possible to create a DbCommand using the factory method available on the connection.

objDbCon.CreateCommand();  

However, I could not find anything to create a DbDataAdapter. Is this is a bug in ADO.NET or what?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

靖瑶 2024-09-21 03:04:21

.NET 4.5开始,在编写独立于提供程序的代码时,您现在可以使用 DbProviderFactories.GetFactory 重载接受 DbConnection 获取正确的提供程序工厂,然后您可以从中创建数据适配器。

示例:

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

似乎 ADO.NET 团队中的某个人阅读了 Ian Boyd 对他的答案的评论...:)

As of .NET 4.5, when writing provider independent code, you can now use the DbProviderFactories.GetFactory overload that accepts a DbConnection to obtain the correct provider factory from which you can then create a data adapter.

Example:

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

It seems someone on the ADO.NET team read Ian Boyd comment on his answer... :)

匿名。 2024-09-21 03:04:21

DbProviderFactory.CreateDataAdapter *

您也可以通过 DbProviderFactories 类获取所有已注册的 DbProvider 。

*我认为这个方法有一个错误的地方。

DbProviderFactory.CreateDataAdapter *

Also you can get all registered DbProviders via DbProviderFactories class.

*I think this is a wrong place for this method.

笑看君怀她人 2024-09-21 03:04:21

虽然 Sergey 很好地回答了这个问题,但我花了一些时间才将其转化为我自己的需求。所以我的理解是,如果您有 DbConnection 但知道您在幕后使用 SqlClient,您的代码将类似于:

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

Although this was answered well by Sergey, it took me a little while to translate it to my own needs. So my understanding was that if you had a DbConnection but knew you were using a SqlClient under the hood your code would look something like:

DbDataAdapter da = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateDataAdapter();
晨敛清荷 2024-09-21 03:04:21
 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;
 }
 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;
 }
山有枢 2024-09-21 03:04:21

您可以使用另一种方式将数据获取到 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;

You can use another way to get data into DataTable without DbDataAdapter.

Here is my code

                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;
豆芽 2024-09-21 03:04:21

鉴于您不知道给定的连接类型,.NET 没有提供解决该问题的好方法。这是我们使用的:

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

Given that you don't know the type of connection you are given, .NET provides no good way to solve the problem. Here's what we use:

/// <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;
}
旧时模样 2024-09-21 03:04:21

死灵术。
如果您低于 .NET 4.5,则可以通过与已编译的 Linq-Expression 的连接从受保护的属性 DbProviderFactory 获取它:

namespace System.Data.Common
{


    public static class ProviderExtensions  
    {

        private static System.Func<System.Data.Common.DbConnection, System.Data.Common.DbProviderFactory> s_func;


        static ProviderExtensions()
        {
            System.Linq.Expressions.ParameterExpression p = System.Linq.Expressions.Expression.Parameter(typeof(System.Data.Common.DbConnection));
            System.Linq.Expressions.MemberExpression prop = System.Linq.Expressions.Expression.Property(p, "DbProviderFactory");
            System.Linq.Expressions.UnaryExpression con = System.Linq.Expressions.Expression.Convert(prop, typeof(System.Data.Common.DbProviderFactory));
            System.Linq.Expressions.LambdaExpression exp = System.Linq.Expressions.Expression.Lambda(con, p);
            s_func = (Func<System.Data.Common.DbConnection, System.Data.Common.DbProviderFactory>)exp.Compile();
        } // End Static Constructor  


        public static System.Data.Common.DbProviderFactory GetProviderByReflection(System.Data.Common.DbConnection conn)
        {
            System.Type t = conn.GetType();
            System.Reflection.PropertyInfo pi = t.GetProperty("DbProviderFactory", 
                  System.Reflection.BindingFlags.NonPublic 
                | System.Reflection.BindingFlags.Instance
            );

            return (System.Data.Common.DbProviderFactory)pi.GetValue(conn);
        } // End Function GetProviderByReflection 


        public static System.Data.Common.DbProviderFactory GetProvider(this System.Data.Common.DbConnection connection)
        {
            return s_func(connection);
        } // End Function GetProvider 


        public static System.Data.Common.DbDataAdapter CreateDataAdapter(this System.Data.Common.DbConnection connection)
        {
            System.Data.Common.DbProviderFactory fact = GetProvider(connection);

            return fact.CreateDataAdapter();
        } // End Function CreateDataAdapter 


        public static System.Data.Common.DbDataAdapter CreateDataAdapter(this System.Data.Common.DbConnection connection, System.Data.Common.DbCommand cmd)
        {
            System.Data.Common.DbProviderFactory fact = GetProvider(connection);

            System.Data.Common.DbDataAdapter da = fact.CreateDataAdapter();
            da.SelectCommand = cmd;

            return da;
        } // End Function CreateDataAdapter 


    }


}

Necromancing.
If you're below .NET 4.5, then you can get it from the protected property DbProviderFactory from the connection with a compiled Linq-Expression:

namespace System.Data.Common
{


    public static class ProviderExtensions  
    {

        private static System.Func<System.Data.Common.DbConnection, System.Data.Common.DbProviderFactory> s_func;


        static ProviderExtensions()
        {
            System.Linq.Expressions.ParameterExpression p = System.Linq.Expressions.Expression.Parameter(typeof(System.Data.Common.DbConnection));
            System.Linq.Expressions.MemberExpression prop = System.Linq.Expressions.Expression.Property(p, "DbProviderFactory");
            System.Linq.Expressions.UnaryExpression con = System.Linq.Expressions.Expression.Convert(prop, typeof(System.Data.Common.DbProviderFactory));
            System.Linq.Expressions.LambdaExpression exp = System.Linq.Expressions.Expression.Lambda(con, p);
            s_func = (Func<System.Data.Common.DbConnection, System.Data.Common.DbProviderFactory>)exp.Compile();
        } // End Static Constructor  


        public static System.Data.Common.DbProviderFactory GetProviderByReflection(System.Data.Common.DbConnection conn)
        {
            System.Type t = conn.GetType();
            System.Reflection.PropertyInfo pi = t.GetProperty("DbProviderFactory", 
                  System.Reflection.BindingFlags.NonPublic 
                | System.Reflection.BindingFlags.Instance
            );

            return (System.Data.Common.DbProviderFactory)pi.GetValue(conn);
        } // End Function GetProviderByReflection 


        public static System.Data.Common.DbProviderFactory GetProvider(this System.Data.Common.DbConnection connection)
        {
            return s_func(connection);
        } // End Function GetProvider 


        public static System.Data.Common.DbDataAdapter CreateDataAdapter(this System.Data.Common.DbConnection connection)
        {
            System.Data.Common.DbProviderFactory fact = GetProvider(connection);

            return fact.CreateDataAdapter();
        } // End Function CreateDataAdapter 


        public static System.Data.Common.DbDataAdapter CreateDataAdapter(this System.Data.Common.DbConnection connection, System.Data.Common.DbCommand cmd)
        {
            System.Data.Common.DbProviderFactory fact = GetProvider(connection);

            System.Data.Common.DbDataAdapter da = fact.CreateDataAdapter();
            da.SelectCommand = cmd;

            return da;
        } // End Function CreateDataAdapter 


    }


}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文