簡體   English   中英

如何在給定DbCommand或DbConnection的情況下創建DbDataAdapter?

[英]How to create a DbDataAdapter given a DbCommand or DbConnection?

我想創建一個適用於任何數據提供者的數據訪問層。

我知道可以使用連接上可用的工廠方法創建DbCommand

objDbCon.CreateCommand();  

但是,我找不到任何東西來創建DbDataAdapter 這是ADO.NET中的一個錯誤還是什么?

.NET 4.5開始 ,在編寫與提供程序無關的代碼時,您現在可以使用接受DbConnectionDbProviderFactories.GetFactory重載來獲取正確的提供程序工廠,然后可以從中創建數據適配器。

例:

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

似乎有人在ADO.NET團隊中讀到了Ian Boyd評論他的回答...... :)

DbProviderFactory.CreateDataAdapter *

您還可以通過DbProviderFactories類獲取所有已注冊的DbProviders。

*我覺得這個方法錯了。

雖然謝爾蓋很好地回答了這個問題,但我花了一點時間才將其翻譯成我自己的需要。 所以我的理解是,如果你有一個DbConnection,但知道你在底層使用SqlClient,你的代碼看起來像:

DbDataAdapter da = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateDataAdapter();
 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;
 }

鑒於您不知道給定的連接類型,.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;
}

您可以使用其他方法在沒有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;

Necromancing。
如果您的.NET 4.5以下,那么您可以從受保護的屬性DbProviderFactory中獲取它與已編譯的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 


    }


}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM