如何在给定DbCommand或DbConnection的情况下创建DbDataAdapter?
我想创建一个适用于任何数据提供者的数据访问层。
我知道可以使用连接上可用的工厂方法创建DbCommand
。
objDbCon.CreateCommand();
但是,我找不到任何创建DbDataAdapter
东西。 这是ADO.NET中的错误还是什么?
DbProviderFactory.CreateDataAdapter *
您还可以通过DbProviderFactories类获取所有已注册的DbProviders。
*我觉得这个方法错了。
从.NET 4.5开始 ,在编写与提供程序无关的代码时,您现在可以使用接受DbConnection
的DbProviderFactories.GetFactory
重载来获取正确的提供程序工厂,然后可以从中创建数据适配器。
例:
DbDataAdapter CreateDataAdapter(DbConnection connection) { return DbProviderFactories.GetFactory(connection).CreateDataAdapter(); }
似乎有人在ADO.NET团队中读到Ian Boyd评论他的回答…… 🙂
尽管谢尔盖很好地回答了这个问题,但我花了一点时间将其翻译成我自己的需要。 所以我的理解是,如果你有一个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没有提供解决问题的好方法。 这是我们使用的:
/// /// 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. /// /// /// Throws Exception if the connection is not of a known type. /// 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; }
您可以使用其他方法将数据导入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;
Necromancing。
如果您的.NET 4.5以下,那么您可以从受保护的属性DbProviderFactory中获取它与已编译的Linq-Expression的连接:
namespace System.Data.Common { public static class ProviderExtensions { private static System.Func 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)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 } }