繁体   English   中英

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

[英]C# Design Pattern for Database Helper classes

我正在设计一个将由数百个客户端调用的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实现它,然后开发一个实现相同接口的OracleDBManager 问题是我的类是静态的,静态类不能实现接口。 我希望我的助手类保持静态,它更实用,而且每次我需要运行查询时都不必创建新对象。 我还想过使用类继承,但是我不能使用statis虚方法,因此在那里使用不多。 我考虑过一些单例实现,所以我不必创建类,但是我会在多线程访问上遇到麻烦。
什么是最好的设计模式,所以我可以在多线程场景(非常重要)上有很好的性能,没有太多工作编码生产力(不必创建很多类),并且有OracleDBManagerSqlDBManager的标准方法班? 标准方法非常重要,因为我不希望使用这些帮助程序类的代码知道它们是否连接到Oracle或Sql Server。
我确实考虑过使用ORM解决方案,例如Entity Framework 4和nHibernate,但性能影响太大了。 由于我将运行简单查询,因此PL-SQL和TSQL之间的查询语法差异无关紧要。
任何意见和想法将不胜感激。 TKS

为什么不将静态方法设为私有 ,将类包装在接口中以支持MS-SQL / Oracle,并在各自的接口中调用私有静态方法?

例如:

public interface ISqlDbManager
{
   void SaveOrder(Order o);
   void FindOrderById(int orderId);
}

public class SqlServerDbManager : ISqlDbManager
{
    private static void RunSql(String pSql, DBParamsHelper pDBParams, String   pConnStringConfigName)
    {
       // implement as you did above
    }

   public void FindOrderById(int orderId)
   {
      // create SQL, call private "RunSql" method.
   }
}

对其他实现(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(...);

此代码未经测试,但希望您能得到这个想法。 我为我的一个项目使用类似的解决方案,我需要从不同的数据存储中获取数据。 战略和工厂模式简化了这一过程。

希望有所帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM