创建通用/抽象" DBContext"不同DB之间共享功能的类

时间:2015-06-22 14:16:26

标签: c# database generics inheritance abstract-class

我正在开发一个C#项目,该项目在不同时间从SQL ServerODBC data-sourcesOracle Databases提取数据。

此时,我创建了3个不同的类 - 每种类型的数据库访问一次。但是,我发现每个库中95%的代码是相同的 - 主要区别在于创建ConnectionCommand对象。

作为课程内容的一个非常简单的例子,这里可以作为一个例子:

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

基本上,我需要从每个数据库获取相同类型的返回数据,并且这样做的方法几乎相同,不同的是ConnectionCommand - 类型对象。

现在,当我查看两个连接对象时,我发现它们都继承自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'

等错误

我非常喜欢新手,任何帮助/示例代码/链接到过去做得很好的方式都非常非常赞赏!

感谢!!!

3 个答案:

答案 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;
}