数据库助手类的C#设计模式

数据库助手类的C#设计模式,c#,design-patterns,C#,Design Patterns,我正在设计一个WCF服务,它将被数百个客户机调用,我有一个关于数据库查询运行的类的最佳体系结构的问题。今天,我只访问SQL Server,所以我有一个静态类,我在内部调用它来完成创建连接和数据读取器的所有脏活。下面是一个简单的例子: namespace DBHelper.Utility { public static class SqlDBManager { public static void RunSql(String pSql, DBParamsHelper pDBPara

我正在设计一个WCF服务,它将被数百个客户机调用,我有一个关于数据库查询运行的类的最佳体系结构的问题。今天,我只访问SQL Server,所以我有一个静态类,我在内部调用它来完成创建连接和数据读取器的所有脏活。下面是一个简单的例子:

namespace DBHelper.Utility
{
  public static class SqlDBManager
  {
    public static void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName)
    {
      String sConnectionString = GetConnectionStringFromConfig(pConnStringConfigName);
      SqlConnection oConn = new SqlConnectionsConnectionString 
      oConn.Open();
      try
      {
        SqlCommand oCommand = new SqlCommand(pSql, oConn);
        oCommand.CommandTimeout = 0;
        if (pDBManagerParams != null)
        {
          foreach (SqlParameter sqlParam in pDBManagerParams)
          {
            oCommand.Parameters.Add(sqlParam);
          }
        }
        oCommand.ExecuteNonQuery();
      }
      finally
      {
        oConn.Close();
      }
    }
  }
}
现在,我需要添加对运行Sql Server和Oracle的支持。我最初的想法是声明一个接口,让我现有的
SqlDBManager
实现它,然后开发一个
oracledmanager
实现相同的接口。问题是我的类是静态的,静态类不能实现接口。我希望我的helper类保持静态,因为它更实用,并且我不必每次需要运行查询时都创建一个新对象。我也想过使用类继承,但是我不能使用statis虚拟方法,所以在那里没有太多的用途。我考虑了一些单例实现,这样我就不必创建类,但这样我在多线程访问方面就会遇到问题。
最好的设计模式是什么,这样我就可以在多线程场景中获得出色的性能(非常重要),不需要太多的工作来提高效率(不需要创建大量的类),并且对于
OracleDBManager
SqlDBManager
类都有一个标准方法?标准方法非常重要,因为我不想让使用这些助手类的代码知道它们是否连接到Oracle或Sql Server。
我确实考虑过使用ORM解决方案,如实体框架4和NHiBiNATE,但是性能的影响太大。由于我将运行简单的查询,PL-SQL和TSQL之间的查询语法差异并不重要。

任何意见和想法都将不胜感激。Tks

为什么不将静态方法设置为私有方法,将类封装在支持MS-SQL/Oracle的接口中,并在相应的接口中调用私有静态方法

例如:

对另一个实现(OracleDbManager)执行相同的操作

将其私有化是有意义的,因为消费者不应该关心底层持久性机制如何工作

这也将使单元测试更容易——创建一个“MockDbManager”类,其中私有静态方法对内存列表执行基本的LINQ操作


另一方面,我强烈建议使用存储过程,而不是手动构造sql命令。查询计划缓存/优化更好。

为什么不将静态方法设置为私有方法,将类封装在接口中以支持MS-SQL/Oracle,并在相应的接口中调用私有静态方法

例如:

对另一个实现(OracleDbManager)执行相同的操作

将其私有化是有意义的,因为消费者不应该关心底层持久性机制如何工作

这也将使单元测试更容易——创建一个“MockDbManager”类,其中私有静态方法对内存列表执行基本的LINQ操作


另一方面,我强烈建议使用存储过程,而不是手动构造sql命令。查询计划缓存/优化更好。

接口是正确的方向,但正如您所指出的,您不能让静态类实现接口。我知道我想尽量减少对象创建的麻烦,但为了拥有两个不同的数据库类,这在某种程度上可能是必要的

我建议的解决方案是多方面的。首先是一个具有类似于上面所列签名的接口:

public Interface IDbManager {
     void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName)
}
这可以在SQL和Oracle特定版本中实现,您已经有了SQL版本,只需将其设置为非静态并实现接口即可

现在,请尝试数据库工厂,可能如下所示:

public static class DbFactory {
    public static IDbManager CreateDb(DbType type) {
        select (type) {
            case DbType.Sql:
                return new SqlDbManager();
                break;
            case DbType.Sql:
                return new OracleDbManager();
                break;
        }
    }
}
然后,您应该能够执行以下操作:

var db = DbFactory.CreateDb(DbType.Sql);
db.RunQuery(...);
这段代码未经测试,但希望您能理解。我在我的一个项目中使用了类似的解决方案,我需要从不同的数据存储中获取数据。战略和工厂模式简化了这一过程


希望有帮助

接口是正确的方向,但正如您所指出的,不能让静态类实现接口。我知道我想尽量减少对象创建的麻烦,但为了拥有两个不同的数据库类,这在某种程度上可能是必要的

我建议的解决方案是多方面的。首先是一个具有类似于上面所列签名的接口:

public Interface IDbManager {
     void RunSql(String pSql, DBParamsHelper pDBParams, String pConnStringConfigName)
}
这可以在SQL和Oracle特定版本中实现,您已经有了SQL版本,只需将其设置为非静态并实现接口即可

现在,请尝试数据库工厂,可能如下所示:

public static class DbFactory {
    public static IDbManager CreateDb(DbType type) {
        select (type) {
            case DbType.Sql:
                return new SqlDbManager();
                break;
            case DbType.Sql:
                return new OracleDbManager();
                break;
        }
    }
}
然后,您应该能够执行以下操作:

var db = DbFactory.CreateDb(DbType.Sql);
db.RunQuery(...);
这段代码未经测试,但希望您能理解。我在我的一个项目中使用了类似的解决方案,我需要从不同的数据存储中获取数据。战略和工厂模式简化了这一过程


希望有帮助

我完全同意procs的建议。但是,我需要为每个业务对象重复数据库代码,对吗?@Pascal-correct。怎么了?每个对象的一组CRUD进程。这样你就可以把它们分开。ATM每个对象都使用一种方法。@RPM194现在我明白你的意思了。。但是我的类是帮助类,它们集中了那些无聊的东西来实际运行过程/查询。我真的很感谢你的意见,以及你为你的建议投入的时间,这是一个好主意,但它不符合我目前的需要。但是谢谢你。我完全同意procs的建议。但是,我需要为每个业务对象重复数据库代码,对吗?@Pascal-corre