我正在开发一个C#项目,该项目在不同时间从SQL Server
,ODBC data-sources
和Oracle Databases
提取数据。
此时,我创建了3个不同的类 - 每种类型的数据库访问一次。但是,我发现每个库中95%的代码是相同的 - 主要区别在于创建Connection
和Command
对象。
作为课程内容的一个非常简单的例子,这里可以作为一个例子:
public class Oracle
{
static DataTable exec_DT(string query, string conn_str)
{
DataTable retVal = new DataTable();
using (OracleConnection conn = new OracleConnection(conn_str))
using (OracleCommand cmd = new OracleCommand(query, conn))
{
conn.Open();
using (OracleDataReader rdr = cmd.ExecuteReader())
{
retVal.Load(rdr);
rdr.Close();
}
}
return retVal;
}
}
和
public class SQLServer
{
static DataTable exec_DT(string query, string conn_str)
{
DataTable retVal = new DataTable();
using (SqlConnection conn = new SqlConnection(conn_str))
using (SqlCommand cmd = new SqlCommand(query, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
retVal.Load(rdr);
rdr.Close();
}
}
return retVal;
}
}
基本上,我需要从每个数据库获取相同类型的返回数据,并且这样做的方法几乎相同,不同的是Connection
和Command
- 类型对象。
现在,当我查看两个连接对象时,我发现它们都继承自DbConnection
:
public sealed class SqlConnection : DbConnection, ICloneable
public sealed class OracleConnection : DbConnection, ICloneable
但我仍然无法想出一个创建通用/抽象父类的好方法,因为DBConnection / DBCommand类是抽象的,当我尝试一些东西时,可以停止对这种代码重复的需求。以下几行:
using (DbConnection conn = new DbConnection(conn_str))
using (DbCommand cmd = new DbCommand(query, conn))
我收到Cannot create an instance of the abstract class or interface 'System.Data.Common.DbCommand'
我非常喜欢新手,任何帮助/示例代码/链接到过去做得很好的方式都非常非常赞赏!
感谢!!!
答案 0 :(得分:2)
这里的关键是退后一步,从另一个角度思考问题。您正在复制大量代码,因为您正在方法中创建数据库和命令类的实例。所以请注入它们:
aiohttp
这种方法具有附加值,您可以通过创建模拟public class SomeDBClass
{
static DataTable exec_DT(DBConnection conn, DBCommand cmd)
{
DataTable retVal = new DataTable();
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
retVal.Load(rdr);
rdr.Close();
}
return retVal;
}
}
和exec_DT
来测试DBConnection
,而无需SQLServer或Oracle,然后将其注入到测试用例中
答案 1 :(得分:1)
我喜欢David's answer。或者,如果您仍然希望从共享代码中创建连接和命令,那么您可以做的是将DbProviderFactory
实例传递给“DB Context”类的构造函数。
然后您可以拨打电话,例如<{1}},jobs -l %
或您需要在每种方法中创建的任何其他内容。
答案 2 :(得分:0)
DbProviderFactory
课程完全符合您的要求。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ledonoff"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".Led_bluetooth"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
</manifest>
您甚至可以使用DbProviderFactories
类从配置文件中的连接字符串创建工厂实例。
static DataTable exec_DT(string query, string conn_str)
{
DataTable retVal = new DataTable();
using (DbConnection conn = MyDbProvider.CreateConnection())
{
conn.ConnectionString = conn_str;
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = query;
conn.Open();
using (DbDataReader rdr = cmd.ExecuteReader())
{
retVal.Load(rdr);
rdr.Close();
}
}
}
return retVal;
}