【问题标题】:How to create a DbDataAdapter given a DbCommand or DbConnection?如何在给定 DbCommand 或 DbConnection 的情况下创建 DbDataAdapter?
【发布时间】:2011-03-30 04:08:34
【问题描述】:

我想创建一个适用于任何数据提供者的数据访问层。

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

objDbCon.CreateCommand();  

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

【问题讨论】:

    标签: c# ado.net


    【解决方案1】:

    .NET 4.5 开始,在编写与提供程序无关的代码时,您现在可以使用接受 DbConnectionDbProviderFactories.GetFactory 重载来获取正确的提供程序工厂,然后您可以从中创建一个数据适配器。

    例子:

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

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

    【讨论】:

    • 我刚刚搜索了这个问题的解决方案;一年之后。我的硬编码案例不处理SqlCeConnectionSqlCeDataAdapter。而且由于这是共享代码,我不想强​​迫每个客户在他们甚至不使用它时安装SQL Server CE。感谢您首先找到了应该需要的东西!
    • 写在 GetFactory(connection) 仅在 .net 4.5 中工作的任何地方吗?因为MSDN 说它支持4.0,但在我的情况下不是。
    • 知道如何将它与IDbConnection 一起使用吗?
    【解决方案2】:

    DbProviderFactory.CreateDataAdapter*

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

    *我认为这个方法的地方不对。

    【讨论】:

    • 给定一个DbCommandDbConnection,如何得到对应的DbProviderFactory
    【解决方案3】:

    虽然 Sergey 很好地回答了这个问题,但我还是花了一点时间才把它翻译成我自己的需要。所以我的理解是,如果你有一个 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'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;
        }
        

        【讨论】:

        • @Karim 我有 love 更好的解决方案。我会想到connection.CreateAdapater,或DbProviderFactories.GetFactory(connection),或DbProviderFactories.GetFactory(typeof(connection)),或某事
        • 请注意,这似乎是 ADO.NET 团队从 .NET 4.5 开始实际实现的内容。
        • DbDataAdapter da = new Microsoft.Data.SqlClient.SqlDataAdapter();也可以添加一个。
        • @JaydeepShil SqlClient (SQL Server) 不适用于 Oracle。
        【解决方案6】:

        您可以使用另一种方式在没有 DbDataAdapter 的情况下将数据放入 DataTable。

        这是我的代码

                        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;
        

        【讨论】:

        • 谢谢 - 这应该是选择的答案
        【解决方案7】:

        死灵术。
        如果您低于 .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 
        
        
            }
        
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-14
          • 2011-05-04
          相关资源
          最近更新 更多