我正在设计一个将由数百个客户端调用的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虚方法,因此在那里使用不多。我考虑过一些单例实现,所以我不必创建类,但是我会在多线程访问上遇到麻烦
什么是最好的设计模式,所以我可以在多线程场景(非常重要)上有很好的性能,没有太多工作编码生产力(不必创建很多类),并且有{{1的标准方法}和OracleDBManager
类?标准方法非常重要,因为我不希望使用这些帮助程序类的代码知道它们是否连接到Oracle或Sql Server。
我确实考虑过使用ORM解决方案,例如Entity Framework 4和nHibernate,但性能影响太大了。由于我将运行简单查询,因此PL-SQL和TSQL之间的查询语法差别无关紧要
任何意见和想法将不胜感激。 TKS
答案 0 :(得分:2)
为什么不将静态方法私有,在接口中包装类以支持MS-SQL / Oracle,并在相应的接口中调用私有静态方法?
E.g:
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命令。更适合查询计划缓存/优化。
答案 1 :(得分:2)
接口是正确的方向,但正如您所指出的,您不能让静态类实现接口。我理解想尽量减少对象创建的麻烦,但为了拥有两个不同的数据库类,这可能是必要的。
我建议的解决方案是多方面的。首先是一个签名类似于上面列出的签名的界面:
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(...);
此代码未经测试,但希望您明白这一点。我为我的一个项目使用类似的解决方案,我需要从不同的数据存储中获取数据。战略和工厂模式简化了这一过程。
希望有所帮助!