话说小菜已经做到了支持多数据库的大体设计了.
老大来看小菜,看小菜的进步如何.
看到小菜的设计之后,老大给予了一定的肯定,但还是少不了一些意见.
1)老大对小菜的ForumManage的代码极其不满意.
public class ForumFactory

{
public static IForumManage CreateForumManage()

{
IForumManage forumManage = null;
switch (BaseConfigFileManager.GetDbType)

{
case "Access" :
forumManage = (IForumManage)Assembly.Load("Discuz.Data.Access").CreateInstance("Discuz.Data.Access.ForumManage");
break;
case "SqlServer" :
forumManage = (IForumManage)Assembly.Load("Discuz.Data.SqlServer").CreateInstance("Discuz.Data.SqlServer.ForumManage");
break;
default :
throw new Exception("暂不支持其它数据库类型");
}

return forumManage;
}
}
第一点: 静态CreateForumManage()函数,小菜既然没有考虑到IForumManage每用一次就要被实例化一次.
第二点:代码是否冗余.
小菜对代码进行了改进
using System;
using System.Reflection;
using Discuz.Config;

namespace Discuz.Data


{
public class ForumFactory

{
private static IForumManage m_forumManage = null;
public static IForumManage CreateForumManage()

{
if (m_forumManage == null)

{
try

{
string assembly = string.Format("Discuz.Data.{0}", BaseConfigFileManager.GetDbType);
string typeName = string.Format("Discuz.Data.{0}.ForumManage", BaseConfigFileManager.GetDbType);
m_forumManage = (IForumManage)Assembly.Load(assembly).CreateInstance(typeName);
}
catch

{
throw new Exception("请检查DNT.config中Dbtype节点数据库类型是否正确,例如:SqlServer、Access");
}
}

return m_forumManage;
}
}
}
恩,不错,小菜可教也.
老大继续说到,小菜啊,你看ForumFactory在我们的代码中是独一无二的,而且我们希望它一身只被构造一次.
小菜心领神会(老大的意思是说,这个类更合适使用单件模式来使用.)
using System;
using System.Reflection;
using Discuz.Config;

namespace Discuz.Data


{
public class ForumFactory

{
private static IForumManage m_instance = null;
private static object m_lock = new object();

private ForumFactory()

{}

static ForumFactory()

{
GetProvider();
}

private static void GetProvider()

{
try

{
m_instance = (IForumManage)Activator.CreateInstance(Type.GetType(string.Format("Discuz.Data.{0}.ForumManage, Discuz.Data.{0}",BaseConfigFileManager.GetDbType),false,true));
}
catch

{
throw new Exception("请检查DNT.config中Dbtype节点数据库类型是否正确,例如:SqlServer、Access");
}
}

public static IForumManage GetInstance()

{
if (m_instance == null)

{
lock (m_lock)

{
if (m_instance == null)

{
GetProvider();
}
}
}
return m_instance;
}
}
}

那我们的调用方式也要从IForumManage forum = ForumFactory.CreateForumManage();
改为IForumManage forum = ForumFactory.CetInstance();
其实单件的实现方式有三种,一,二两种比较常见,第三种比较少见,不过却是最好的,上面的代码是第一种.
大家可以参考怪怪的一篇随笔: 对Singleton的实现方法做一个总结
或者直接看这篇 http://www.yoda.arachsys.com/csharp/singleton.html (写的更细心,不过是英文的)
对噢.老大的意见还没说完呢! :)
2)小菜啊,你看代码中的SqlHelper与AccessHelper代码重复太多,而且完成的功能基本类似,所以你得考虑下重构下他们俩兄弟.(老大还给了小菜一个提示: System.Data.Common中已经为我们提供了帮助,可以去看看)
小菜重新打开了System.Data.Common的源码. (发现了如下的代码组织,这不是抽象工厂模式吗.)

图画的不是很好看,大家将就下吧, :)

public abstract class DbProviderFactory
{

protected DbProviderFactory()
{
}

public virtual DbCommand CreateCommand()
{
return null;
}


public virtual DbConnection CreateConnection()
{
return null;
}

public virtual DbParameter CreateParameter()
{
return null;
}
}

public sealed class SqlClientFactory : DbProviderFactory


{
public static readonly SqlClientFactory Instance = new SqlClientFactory();


private SqlClientFactory()
{
}


public override DbCommand CreateCommand()
{
return new SqlCommand();
}


public override DbConnection CreateConnection()
{
return new SqlConnection();
}


public override DbParameter CreateParameter()
{
return new SqlParameter();
}
}

public sealed class OleDbFactory : DbProviderFactory


{
public static readonly OleDbFactory Instance = new OleDbFactory();


private OleDbFactory()
{
}


public override DbCommand CreateCommand()
{
return new OleDbCommand();
}


public override DbConnection CreateConnection()
{
return new OleDbConnection();
}


public override DbParameter CreateParameter()
{
return new OleDbParameter();
}
}
看来老大的提示确实给了小菜不小的帮助.
小菜开始拿起手头的SqlHelper与AccessHelper准备改造了.
using System;
using System.Web;
using System.Data;
using System.Data.Common;
using System.Data.OleDb;
using System.Data.SqlClient;
using Discuz.Config;

namespace Discuz.Data


{
public abstract class DbHelper

{
private static string m_connString;
private static DbProviderFactory m_factory = null;

static DbHelper()

{
switch (BaseConfigFileManager.GetDbType)

{
case "Access":
m_connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
HttpContext.Current.Server.MapPath("~/database/access_db.config"); //Access数据库连接串
m_factory = OleDbFactory.Instance;
break;
case "SqlServer":
m_connString = "Data Source=(local);User ID=sa;Password=password;"+
"Initial Catalog=discuz;Pooling=true"; //Sql数据库连接串
m_factory = SqlClientFactory.Instance;
break;
default:
throw new Exception("暂不支持其它数据库类型");
}
}

private static DbProviderFactory Factory

{
get

{
return m_factory;
}
}


/**//// <summary>
/// 执行一个DbCommand返回一个记录集
/// </summary>
/// <remarks>
/// 例如:
/// DbDataReader r = ExecuteReader(CommandType.Text, "select id,name from dnt_forums", null);
/// </remarks>
/// <param name="cmdType">DbCommand类型</param>
/// <param name="cmdText">DbCommand文本</param>
/// <param name="cmdParms">DbCommand的参数DbParameter</param>
/// <returns>一个包含记录的DbDataReader</returns>
public static DbDataReader ExecuteReader(CommandType cmdType, string cmdText, params DbParameter[] cmdParms)

{
DbCommand cmd = Factory.CreateCommand();
DbConnection conn = Factory.CreateConnection();
conn.ConnectionString = m_connString;

try

{
PrepareCommand(cmd, conn, cmdType, cmdText, cmdParms);
DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return rdr;
}
catch (Exception ex)

{
conn.Close();
throw ex;
}
}


/**//// <summary>
/// 执行一个DbCommand并返回第一条记录的第一列的值
/// </summary>
/// <remarks>
/// 例如:
/// SqlParameter parm = new SqlParameter("@fid", SqlDbType.Int, 4);
/// parm.Value = fid;
/// Object obj = ExecuteScalar(CommandType.Text, "select name from dnt_forums where fid=@fid", parm);
/// 或者
/// OleDbParameter parm = new OleDbParameter("@fid", OleDbType.Integer, 4);
/// parm.Value = fid;
/// Object obj = ExecuteScalar(CommandType.Text, "select name from dnt_forums where fid=@fid", parm);

/// </remarks>
/// <param name="cmdType">DbCommand类型</param>
/// <param name="cmdText">DbCommand文本</param>
/// <param name="cmdParms">DbCommand的参数DbParameter</param>
/// <returns>返回第一条记录的第一列的值</returns>
public static object ExecuteScalar(CommandType cmdType, string cmdText, params DbParameter[] cmdParms)

{
DbCommand cmd = Factory.CreateCommand();

using (DbConnection conn = Factory.CreateConnection())
