数据提供者抽象
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 种系统类型执行操作,但如果可用的话,我想提供专门对象构造的能力。
问题
- 除了 Entity Framework 之外还有更好的方法吗?
- 我是否在重复现有的工作(在 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 的方法,您的底层方法需要知道是谁创建了该连接,以及它是 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);
}
我有一个场景,我需要将来自几个不同数据提供者的公共 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 种系统类型执行操作,但如果可用的话,我想提供专门对象构造的能力。
问题
- 除了 Entity Framework 之外还有更好的方法吗?
- 我是否在重复现有的工作(在 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 的方法,您的底层方法需要知道是谁创建了该连接,以及它是 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);
}