数据提供者抽象

Data Provider Abstraction

我有一个场景,我需要将来自几个不同数据提供者的公共 class 成员抽象为一个公共 class。当前的数据对象全部派生自 System.Data.Common 命名空间中的各种 Db* classes。

下面是我当前的 base 实现:

public abstract class DataProvider<TConn, TCmd, TParam> : IDisposable
    where TConn : DbConnection, new()
    where TCmd : DbCommand, new() {

    public DataProvider ( string connstr ) {
        ConnectionString = connstr;
    }

    public TConn Connection { get { return new TConn(); } }
    public TCmd Command { get { return new TCmd(); } }
    public string ConnectionString { get; private set; }

    protected DbDataReader ExecuteReader ( string text , CommandType type , params TParam [] parms ) {
        try {
            using ( var conn = Connection ) {
                conn.Open();

                using ( var cmd = Command ) {
                    cmd.CommandText = text;
                    cmd.CommandType = type;
                    cmd.Parameters.AddRange( parms );

                    return cmd.ExecuteReader();
                }
            }
        } catch ( Exception ex ) {
            Log.Exception( ex , GetType().Name );
            throw ex;
        }
    }
}

我目前的两个实现:

public class SqlDataProvider : DataProvider<SqlConnection, SqlCommand, SqlParameter> {
    public SqlDataProvider ( string connstr ) : base( connstr ) { }

    public DataTable ExecuteStoredProcedure(string text, params SqlParameter[] parms ) {
        var dt = new DataTable();
        dt.Load( ExecuteReader( text , CommandType.StoredProcedure , parms ) );
        return dt;
    }

    public DataTable ExecuteStatement(string text, params SqlParameter[] parms ) {
        var dt = new DataTable();
        dt.Load( ExecuteReader( text , CommandType.Text , parms ) );
        return dt;
    }
}

public class OleDataProvider : DataProvider<OleDbConnection, OleDbCommand, OleDbParameter> {
    public OleDataProvider ( string connstr ) : base( connstr ) { }

    public DataTable ExecuteStoredProcedure(string text, params OleDbParameter[] parms ) {
        var dt = new DataTable();
        dt.Load( ExecuteReader( text , CommandType.StoredProcedure , parms ) );
        return dt;
    }

    public DataTable ExecuteStatement(string text, params OleDbParameter[] parms ) {
        var dt = new DataTable();
        dt.Load( ExecuteReader( text , CommandType.Text , parms ) );
        return dt;
    }
}

最终,我正在尝试建立一个框架,以便将来扩展到派生自 Db* 对象系列的其他数据库对象。

当前产品连接到 MS-SQL、Sybase、Informatica 和 Oracle。我知道 OleDb 可以为所有 4 种系统类型执行操作,但如果可用的话,我想提供专门对象构造的能力。

问题

  1. 除了 Entity Framework 之外还有更好的方法吗?
  2. 我是否在重复现有的工作(在 EF and/or ADO 之外)

您唯一需要的类型是连接类型。该连接提供了创建其后续对象的所有方法。

示例:

using(var connection = new TConnection())
{
    using(var command = connection.CreateCommand())
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = "@answer";
        parameter.Value = 42;

        command.Parameters.Add(parameter);

        /// and so forth
    }
}

您甚至可以将其从实际泛型中移走...这是运行时行为。您所需要的只是采用 IDbConnection 和 none 的方法,您的底层方法需要知道是谁创建了该连接,以及它是 SqlConnectionOracleConnection 还是任何其他。

void MyAgnosticDatabaseMethod(IDbConnection connection)
{
    using(var command = connection.CreateCommand())
    {
        var parameter = command.CreateParameter();
        parameter.ParameterName = "@answer";
        parameter.Value = 42;

        command.Parameters.Add(parameter);

        /// and so forth
    }
}

然后:

using(var connection = new OracleConnection())
{
    MyAgnosticDatabaseMethod(connection);
}

using(var connection = new SqlConnection())
{
    MyAgnosticDatabaseMethod(connection);
}