我有一个场景,我需要将几个不同的数据提供者中的公共类成员抽象为一个公共类。当前的Data对象都派生自Db*
命名空间中的各种System.Data.Common
类。
以下是我当前的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种系统类型的操作,但是如果可用的话,它们可以提供专门的对象结构的能力。
答案 0 :(得分:1)
您需要的唯一类型是连接类型。该连接提供了创建后续对象的所有方法。
示例:
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
的方法,而您的基本方法都不需要知道谁创建了该连接,以及它是SqlConnection
,OracleConnection
还是其他任何连接。
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);
}