petshop通过抽象工厂实现了数据库的自由切换,但是我不喜欢这种方式。一是需要多建好几个项目,每一个数据库都要一个DAL和Help类。项目多了,代码量自然也多了,维护起来不方便,修改一个东西要改动好几个地方。
它是在DAL层面实现的数据库切换,几个Help没有什么联系,而且代码大量重复。为什么不在Help类里实现数据库里切换呢~这样只需要一个DAL,在配置文件里改一下,Help类就会返回不同数据库的对象供DAL使用。怎么实现呢,我想到了两种方式。
第一个自然是反射,使用System.Data.Common命名空间的类,代码如下:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data;
using System.Data.Common;
using System.Collections;
namespace Jdpc.DBHelper
{
/// <summary>
/// 数据库的通用访问代码
/// 此类为静态类,不允许实例化,在应用时直接调用即可
/// </summary>
public static class Datahelper
{
private static string assemblyname =DBConfig.AssemblyName;
private static string namespacename = DBConfig.NameSpace;
private static string connectionname = DBConfig.ConnectionName;
private static string dataadaptername = DBConfig.DataAdapterName;
//获取数据库连接字符串,其属于静态变量且只读,项目中所有文档可以直接使用,但不能修改
public static readonly string ConnectionStringLocalTransaction = DBConfig.ConnectString;
/// <summary>
///执行一个不需要返回值的SqlCommand命令,通过指定专用的连接字符串。
/// 使用参数数组形式提供参数列表
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
using (DbConnection conn=(DbConnection)Assembly.Load(assemblyname).CreateInstance(namespacename + "." +connectionname))
{
DbCommand cmd = conn.CreateCommand();
conn.ConnectionString = connectionString;
//通过PrePareCommand方法将参数逐个加入到SqlCommand的参数集合中
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
//清空SqlCommand中的参数列表
cmd.Parameters.Clear();
return val;
}
}
/// <summary>
/// 执行一个不需要返回值的SqlCommand命令,默认使用SQL语句
/// </summary>
/// <param name="cmdText"> T-SQL语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
public static int ExecuteNonQuery(string cmdText, params DbParameter[] commandParameters)
{
return ExecuteNonQuery(ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
/// <summary>
/// 执行一个不需要返回值的SqlCommand命令,不带任何参数
/// </summary>
/// <param name="cmdText">T-SQL语句</param>
/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
public static int ExecuteNonQuery(string cmdText)
{
return ExecuteNonQuery(ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
/// <summary>
///执行一条不返回结果的SqlCommand,通过一个已经存在的数据库连接
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="conn">一个现有的数据库连接</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
public static int ExecuteNonQuery(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
DbCommand cmd = connection.CreateCommand();
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
/// <summary>
/// 执行一条不返回结果的SqlCommand,通过一个已经存在的数据库事物处理
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="trans">一个存在的 sql 事物处理</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此SqlCommand命令执行后影响的行数</returns>
public static int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
DbCommand cmd = trans.Connection.CreateCommand();
PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
/// <summary>
/// 执行多条SQL语句,实现数据库事务。
/// </summary>
/// <param name="SQLStringList">多条SQL语句</param>
public static void ExecuteSqlTran(string connectionString, List<string> SQLStringList)
{
using (DbConnection conn = (DbConnection)Assembly.Load(assemblyname).CreateInstance(namespacename + "." + connectionname))
{
conn.ConnectionString = connectionString;
conn.Open();
DbCommand cmd = conn.CreateCommand();
DbTransaction tx = conn.BeginTransaction();
cmd.Transaction = tx;
try
{
for (int n = 0; n < SQLStringList.Count; n++)
{
string strsql = SQLStringList[n].ToString();
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
cmd.ExecuteNonQuery();
}
}
tx.Commit();
}
catch (System.Data.Common.DbException E)
{
tx.Rollback();
throw new Exception(E.Message);
}
}
}
public static void ExecuteSqlTran(List<string> SQLStringList)
{
ExecuteSqlTran(ConnectionStringLocalTransaction, SQLStringList);
}
/// <summary>
/// 执行一条返回结果集的SqlCommand命令,通过专用的连接字符串。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个包含结果的SqlDataReader</returns>
public static DbDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
DbConnection conn = (DbConnection)Assembly.Load(assemblyname).CreateInstance(assemblyname+ "." + connectionname);
conn.ConnectionString = connectionString;
DbCommand cmd = conn.CreateCommand();
// 在这里使用try/catch处理是因为如果方法出现异常,则SqlDataReader就不存在,
//CommandBehavior.CloseConnection的语句就不会执行,触发的异常由catch捕获。
//关闭数据库连接,并通过throw再次引发捕捉到的异常。
try
{
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return rdr;
}
catch
{
conn.Close();
throw;
}
}
/// <summary>
/// 执行一条返回结果集的SqlCommand命令,默认使用SQL语句
/// </summary>
/// <param name="cmdText">T-SQL语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个包含结果的SqlDataReader</returns>
public static DbDataReader ExecuteReader(string cmdText, params DbParameter[] commandParameters)
{
return ExecuteReader(ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
/// <summary>
/// 执行一条返回结果集的SqlCommand命令,不使用任何参数
/// </summary>
/// <param name="cmdText">T-SQL语句</param>
/// <returns>返回一个包含结果的SqlDataReader</returns>
public static DbDataReader ExecuteReader(string cmdText)
{
return ExecuteReader(ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
/// <summary>
/// 执行一条返回第一条记录第一列的SqlCommand命令,通过专用的连接字符串。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public static Jobject ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
using (DbConnection connection = (DbConnection)Assembly.Load(assemblyname).CreateInstance(namespacename + "." + connectionname))
{
connection.ConnectionString = connectionString;
DbCommand cmd = connection.CreateCommand();
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
Jobject val = new Jobject(cmd.ExecuteScalar());
cmd.Parameters.Clear();
return val;
}
}
/// <summary>
/// 执行一条返回第一条记录第一列的SqlCommand命令,默认使用SQL语句
/// </summary>
/// <param name="cmdText">T-SQL语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public static Jobject ExecuteScalar(string cmdText, params DbParameter[] commandParameters)
{
return ExecuteScalar(ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
/// <summary>
/// 执行一条返回第一条记录第一列的SqlCommand命令,不使用参数
/// </summary>
/// <param name="cmdText">T-SQL语句</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public static Jobject ExecuteScalar(string cmdText)
{
return ExecuteScalar(ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
/// <summary>
/// 执行一条返回第一条记录第一列的SqlCommand命令,通过已经存在的数据库连接。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24));
/// </remarks>
/// <param name="conn">一个已经存在的数据库连接</param>
/// <param name="commandType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-SQL 语句</param>
/// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public static Jobject ExecuteScalar(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
DbCommand cmd = connection.CreateCommand();
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
Jobject val = new Jobject(cmd.ExecuteScalar());
cmd.Parameters.Clear();
return val;
}
/// <summary>
/// 执行查询语句,返回DataSet
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="SQLString">查询语句</param>
/// <returns>DataSet</returns>
public static DataSet ExecuteDataSet(string connectionString, string SQLString)
{
if (SQLString != null && SQLString.Trim() != "")
{
using (DbConnection connection = (DbConnection)Assembly.Load(assemblyname).CreateInstance(namespacename + "." + connectionname))
{
connection.ConnectionString = connectionString;
DataSet ds = new DataSet();
try
{
connection.Open();
DbDataAdapter adapter = (DbDataAdapter)Assembly.Load(assemblyname).CreateInstance(namespacename + "." + dataadaptername);
DbCommand cmd = connection.CreateCommand();
cmd.CommandText=SQLString;
adapter.SelectCommand = cmd;
adapter.Fill(ds, "ds");
}
catch (System.Data.Common.DbException ex)
{
throw new Exception(ex.Message);
}
return ds;
}
}
else
{
return null;
}
}
/// <summary>
/// 执行查询语句,返回DataSet,省略查询字符串
/// </summary>
/// <param name="SQLString">查询语句</param>
/// <returns>DataSet</returns>
public static DataSet ExecuteDataSet(string SQLString)
{
return ExecuteDataSet(ConnectionStringLocalTransaction, SQLString);
}
/// <summary>
/// 为执行命令准备参数
/// </summary>
/// <param name="cmd">SqlCommand 命令</param>
/// <param name="conn">已经存在的数据库连接</param>
/// <param name="trans">数据库事物处理</param>
/// <param name="cmdType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
/// <param name="cmdText">Command text,T-SQL语句 例如 Select * from Products</param>
/// <param name="cmdParms">返回带参数的命令</param>
private static void PrepareCommand(DbCommand cmd, DbConnection conn, DbTransaction trans, CommandType cmdType, string cmdText, DbParameter[] cmdParms)
{
//判断数据库连接状态
if (conn.State != ConnectionState.Open)
conn.Open();
if(cmd.Connection!=null)
cmd.Connection = conn;
cmd.CommandText = cmdText;
//判断是否需要事物处理
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = cmdType;
if (cmdParms != null)
{
foreach (DbParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
}
}
比较不好处理的是DbParameter,程序里用的是DbParameter数组,自然可以接受SqlParameter或OleDbParameter数组,可以像Petshop那样在外部构建一个SqlParameter数组传进来就行了。但是这样客户端就必须知道具体数据库的类型,没有达到封装的目的。我见yueue.ADOKeycap的处理方式不错,但是我的全是静态方法,不能这么搞,于是想了一个笨方法。做了一个类。
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data;
using System.Data.Common;
using System.Collections;
namespace Jdpc.DBHelper
{
public class JDParameter//:DbParameter
{
#region 字段
private static string assemblyname = DBConfig.AssemblyName;
private static string namespacename = DBConfig.NameSpace;
private static string connectionname = DBConfig.ConnectionName;
private static DbCommand cmd = ((DbConnection)Assembly.Load(assemblyname).CreateInstance(namespacename + "." + connectionname)).CreateCommand();
private static DbParameter dbparam =cmd.CreateParameter();
private List<DbParameter> dbparams = new List<DbParameter>();
#endregion 字段
#region 索引器
public DbParameter this[int index]
{
get
{
return dbparams[index];
}
set
{
dbparams[index] = value;
}
}
public DbParameter this[string pname]
{
get
{
for (int i = 0; i < dbparams.Count; i++)
{
if (dbparams[i].ParameterName == pname)
return dbparams[i];
}
return null;
}
set
{
for (int i = 0; i < dbparams.Count; i++)
{
if (dbparams[i].ParameterName == pname)
dbparams[i] = value;
return;
}
throw new Exception("未找到。");
}
}
#endregion 索引器
#region 增加
/// <summary>
/// 设置参数各项并增加到参数列表
/// </summary>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
/// <param name="size">获取或设置列中数据的最大大小(以字节为单位)</param>
/// <param name="value">获取或设置该参数的值。</param>
public void Add(string pname, DbType dtype, int size, object value)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dparam.Size = size;
dparam.Value = value;
dbparams.Add(dparam);
}
/// <summary>
/// 设置参数各项并增加到参数列表
/// </summary>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
/// <param name="size">获取或设置列中数据的最大大小(以字节为单位)</param>
public void Add(string pname, DbType dtype, int size)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dparam.Size = size;
dbparams.Add(dparam);
}
/// <summary>
/// 设置参数各项并增加到参数列表
/// </summary>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
public void Add(string pname, DbType dtype)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dbparams.Add(dparam);
}
/// <summary>
/// 把一个DbParameter增加到参数列表
/// </summary>
/// <param name="dparam">一个DbParameter对象</dparam>
public void Add(DbParameter dparam)
{
dbparams.Add(dparam);
}
/// <summary>
/// 把一个默认的DbParameter增加到参数列表
/// </summary>
/// <param name="dparam">一个DbParameter对象</dparam>
public void Add()
{
dbparams.Add(dbparam);
}
#endregion 增加
#region 插入
/// <summary>
/// 设置参数各项并增加到参数列表指定位置
/// </summary>
/// <param name="index">指定的位置</param>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
/// <param name="size">获取或设置列中数据的最大大小(以字节为单位)</param>
/// <param name="value">获取或设置该参数的值。</param>
public void Insert(int index, string pname, DbType dtype, int size, object value)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dparam.Size = size;
dparam.Value = value;
dbparams.Insert(index, dparam);
}
/// <summary>
/// 设置参数各项并增加到参数列表指定位置
/// </summary>
/// <param name="index">指定的位置</param>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
/// <param name="size">获取或设置列中数据的最大大小(以字节为单位)</param>
public void Insert(int index, string pname, DbType dtype, int size)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dparam.Size = size;
dbparams.Insert(index, dparam);
}
/// <summary>
/// 设置参数各项并增加到参数列表指定位置
/// </summary>
/// <param name="index">指定的位置</param>
/// <param name="pname">获取或设置 JDParameter 的名称</param>
/// <param name="dtype">获取或设置参数的 DbType</param>
public void Insert(int index, string pname, DbType dtype)
{
DbParameter dparam = cmd.CreateParameter();
dparam.ParameterName = pname;
dparam.DbType = dtype;
dbparams.Insert(index, dparam);
}
/// <summary>
/// 把一个DbParameter增加到参数列表指定位置
/// </summary>
/// <param name="index">指定的位置</param>
/// <param name="dparam">一个DbParameter对象</dparam>
public void Insert(int index, DbParameter dparam)
{
dbparams.Insert(index,dparam);
}
/// <summary>
/// 把默认的DbParameter增加到参数列表指定位置
/// </summary>
/// <param name="index">指定的位置</param>
public void Insert(int index)
{
dbparams.Insert(index,dbparam);
}
#endregion 插入
#region 删除
/// <summary>
/// 删除ParameterName为pname的项
/// </summary>
/// <param name="pname">ParameterName属性</param>
public void Remove(string pname)
{
for(int i=0;i<dbparams.Count;i++)
{
if(dbparams[i].ParameterName==pname)
{
dbparams.RemoveAt(i);
}
}
}
/// <summary>
/// 删除指定的DbParameter
/// </summary>
/// <param name="dbp">欲删除的项</param>
public void Remove(DbParameter dbp)
{
dbparams.Remove(dbp);
}
/// <summary>
/// 删除指定位置的项
/// </summary>
/// <param name="index">项的位置</param>
public void RemoveAt(int index)
{
dbparams.RemoveAt(index);
}
/// <summary>
/// 删除从index开始共count个元素
/// </summary>
/// <param name="index">开始位置</param>
/// <param name="count">删除个数</param>
public void RemoveRange(int index, int count)
{
dbparams.RemoveRange(index,count);
}
/// <summary>
/// 全部删除
/// </summary>
public void Clear()
{
dbparams.Clear();
}
#endregion 删除
#region 属性
/// <summary>
/// 获得参数列表
/// </summary>
public DbParameter[] Dbparams
{
get
{
return dbparams.ToArray();
}
}
/// <summary>
/// 获取或设置参数的 DbType。
/// </summary>
public DbType DbType
{
get
{
return dbparam.DbType;
}
set
{
dbparam.DbType = value;
}
}
/// <summary>
/// 获取或设置该参数的值。
/// </summary>
public object Value
{
get
{
return dbparam.Value;
}
set
{
dbparam.Value = value;
}
}
/// <summary>
/// 获取或设置 JDParameter 的名称。
/// </summary>
public string ParameterName
{
get
{
return dbparam.ParameterName;
}
set
{
dbparam.ParameterName = value;
}
}
/// <summary>
/// 获取或设置列中数据的最大大小(以字节为单位)。
/// </summary>
public int Size
{
get
{
return dbparam.Size;
}
set
{
dbparam.Size = value;
}
}
#endregion 属性
}
}
这样就可以像这样调用了。
Code
JDParameter jdp = new JDParameter();
jdp.Add("@UserID", DbType.String, 50);
jdp.Add("@UserKey", DbType.String, 50);
jdp[0].Value = Server.HtmlEncode(txtsmsUID.Text.Trim());
jdp[1].Value = Server.HtmlEncode(txtsmsPWD.Text.Trim());
DbDataReader read = JDBHelper.Datahelper.ExecuteReader("select * from UserTable where UserID=@UserID and UserKey=@UserKey"
这样改造之后应该就可以实现自由切换数据库了。只需修改一下配置文件就Ok。但是我却有点不安,因为在静态方法里使用了反射,每次调用都要反射一次(为了行文方便,这种方法我暂且称之为静态反射),会不会降低性能呢~
于是想到了另一个方法,使用策略模式。先写一个Help的abstract类:
Code
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Data.Common;
using System.Collections.Generic;
namespace Jdpc.DBHelper
{
/// <summary>
/// 数据库的通用访问类的父类
/// </summary>
public abstract class DBStrategy
{
//获取数据库连接字符串,其属于静态变量且只读,项目中所有文档可以直接使用,但不能修改
public readonly string ConnectionStringLocalTransaction = DBConfig.ConnectString;
// 哈希表用来存储缓存的参数信息,哈希表可以存储任意类型的参数。
private Hashtable parmCache = Hashtable.Synchronized(new Hashtable());
protected abstract DbParameter GetParameterType();
internal DbParameter GetDbParameter(string pname, DbType dtype, int size, object value)
{
DbParameter par = GetParameterType();
par.ParameterName = pname;
par.DbType = dtype;
par.Size = size;
par.Value = value;
return par;
}
internal DbParameter GetDbParameter(string pname, DbType dtype, int size)
{
DbParameter par = GetParameterType();
par.ParameterName = pname;
par.DbType = dtype;
par.Size = size;
return par;
}
/// <summary>
///执行一个不需要返回值的DbCommand命令,通过指定专用的连接字符串。
/// 使用参数数组形式提供参数列表
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此DbCommand命令执行后影响的行数</returns>
public abstract int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
///执行一条不返回结果的DbCommand,通过一个已经存在的数据库连接
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(conn, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="conn">一个现有的数据库连接</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此DbCommand命令执行后影响的行数</returns>
public abstract int ExecuteNonQuery(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
/// 执行一条不返回结果的DbCommand,通过一个已经存在的数据库事物处理
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// int result = ExecuteNonQuery(trans, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="trans">一个存在的 Db 事物处理</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个数值表示此DbCommand命令执行后影响的行数</returns>
public abstract int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
/// 执行多条Db语句,实现数据库事务。
/// </summary>
/// <param name="SQLStringList">多条Db语句</param>
public abstract void ExecuteDbTran(string connectionString, List<string> SQLStringList);
/// <summary>
/// 执行一条返回结果集的DbCommand命令,通过专用的连接字符串。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// DbDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个包含结果的DbDataReader</returns>
public abstract DbDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
/// 执行一条返回第一条记录第一列的DbCommand命令,通过专用的连接字符串。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="connectionString">一个有效的数据库连接字符串</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public abstract Jobject ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
/// 执行一条返回第一条记录第一列的DbCommand命令,通过已经存在的数据库连接。
/// 使用参数数组提供参数
/// </summary>
/// <remarks>
/// 使用示例:
/// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new DbParameter("@prodid", 24));
/// </remarks>
/// <param name="conn">一个已经存在的数据库连接</param>
/// <param name="commandType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="commandText">存储过程的名字或者 T-Db 语句</param>
/// <param name="commandParameters">以数组形式提供DbCommand命令中用到的参数列表</param>
/// <returns>返回一个object类型的数据,可以通过 Convert.To{Type}方法转换类型</returns>
public abstract Jobject ExecuteScalar(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters);
/// <summary>
/// 执行查询语句,返回DataSet
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="SQLString">查询语句</param>
/// <returns>DataSet</returns>
public abstract DataSet ExecuteDataSet(string connectionString, string SQLString);
/// <summary>
/// 缓存参数数组
/// </summary>
/// <param name="cacheKey">参数缓存的键值</param>
/// <param name="cmdParms">被缓存的参数列表</param>
public void CacheParameters(string cacheKey, params DbParameter[] commandParameters)
{
parmCache[cacheKey] = commandParameters;
}
/// <summary>
/// 获取被缓存的参数
/// </summary>
/// <param name="cacheKey">用于查找参数的KEY值</param>
/// <returns>返回缓存的参数数组</returns>
public DbParameter[] GetCachedParameters(string cacheKey)
{
DbParameter[] cachedParms = (DbParameter[])parmCache[cacheKey];
if (cachedParms == null)
return null;
//新建一个参数的克隆列表
DbParameter[] clonedParms = new DbParameter[cachedParms.Length];
//通过循环为克隆参数列表赋值
for (int i = 0, j = cachedParms.Length; i < j; i++)
//使用clone方法复制参数列表中的参数
clonedParms[i] = (DbParameter)((ICloneable)cachedParms[i]).Clone();
return clonedParms;
}
/// <summary>
/// 为执行命令准备参数
/// </summary>
/// <param name="cmd">DbCommand 命令</param>
/// <param name="conn">已经存在的数据库连接</param>
/// <param name="trans">数据库事物处理</param>
/// <param name="cmdType">DbCommand命令类型 (存储过程, T-Db语句, 等等。)</param>
/// <param name="cmdText">Command text,T-Db语句 例如 Select * from Products</param>
/// <param name="cmdParms">返回带参数的命令</param>
protected void PrepareCommand(DbCommand cmd, DbConnection conn, DbTransaction trans, CommandType cmdType, string cmdText, DbParameter[] cmdParms)
{
//判断数据库连接状态
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = cmdText;
//判断是否需要事物处理
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = cmdType;
if (cmdParms != null)
{
foreach (DbParameter parm in cmdParms)
cmd.Parameters.Add(parm);
}
}
}
然后不同的数据库重写方法,比如SqlServer的
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
namespace Jdpc.DBHelper
{
class SqlStrategy: DBStrategy
{
protected override DbParameter GetParameterType()
{
return new SqlParameter();
}
public override int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection conn = new SqlConnection(connectionString))
{
//通过PrePareCommand方法将参数逐个加入到SqlCommand的参数集合中
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
//清空SqlCommand中的参数列表
cmd.Parameters.Clear();
return val;
}
}
public override int ExecuteNonQuery(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
public override int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters);
int val = cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
return val;
}
public override void ExecuteDbTran(string connectionString, List<string> SQLStringList)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
SqlTransaction tx = conn.BeginTransaction();
cmd.Transaction = tx;
try
{
for (int n = 0; n < SQLStringList.Count; n++)
{
string strsql = SQLStringList[n].ToString();
if (strsql.Trim().Length > 1)
{
cmd.CommandText = strsql;
cmd.ExecuteNonQuery();
}
}
tx.Commit();
}
catch (System.Data.SqlClient.SqlException E)
{
tx.Rollback();
throw new Exception(E.Message);
}
}
}
public override DbDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
SqlConnection conn = new SqlConnection(connectionString);
// 在这里使用try/catch处理是因为如果方法出现异常,则SqlDataReader就不存在,
//CommandBehavior.CloseConnection的语句就不会执行,触发的异常由catch捕获。
//关闭数据库连接,并通过throw再次引发捕捉到的异常。
try
{
PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return rdr;
}
catch
{
conn.Close();
throw;
}
}
public override Jobject ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
using (SqlConnection connection = new SqlConnection(connectionString))
{
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
Jobject val = new Jobject(cmd.ExecuteScalar());
cmd.Parameters.Clear();
return val;
}
}
public override Jobject ExecuteScalar(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters);
Jobject val = new Jobject(cmd.ExecuteScalar());
cmd.Parameters.Clear();
return val;
}
public override DataSet ExecuteDataSet(string connectionString, string SQLString)
{
if (SQLString != null && SQLString.Trim() != "")
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet ds = new DataSet();
try
{
connection.Open();
SqlDataAdapter command = new SqlDataAdapter(SQLString, connection);
command.Fill(ds, "ds");
}
catch (System.Data.SqlClient.SqlException ex)
{
throw new Exception(ex.Message);
}
return ds;
}
}
else
{
return null;
}
}
}
}
然后是Context类:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data;
using System.Data.Common;
namespace Jdpc.DBHelper
{
public class DBContext
{
private static DBStrategy dbhelp = (DBStrategy)Assembly.GetExecutingAssembly().CreateInstance("Jdpc.DBHelper." + DBConfig.DbClassName);//不知道咋获取当前程序的命名空间
public static DbParameter AddParameter(string pname, DbType dtype, int size, object value)
{
return dbhelp.GetDbParameter(pname,dtype,size,value);
}
public static DbParameter AddParameter(string pname, DbType dtype, int size)
{
return dbhelp.GetDbParameter(pname, dtype, size);
}
public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteNonQuery(connectionString, cmdType, cmdText, commandParameters);
}
public static int ExecuteNonQuery(CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteNonQuery(dbhelp.ConnectionStringLocalTransaction, cmdType, cmdText, commandParameters);
}
public static int ExecuteNonQuery( string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteNonQuery(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
public static int ExecuteNonQuery(string cmdText)
{
return dbhelp.ExecuteNonQuery(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
public static int ExecuteNonQuery(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteNonQuery(connection, cmdType, cmdText, commandParameters);
}
public static int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteNonQuery(trans, cmdType, cmdText, commandParameters);
}
public static void ExecuteDbTran(string connectionString, List<string> SQLStringList)
{
dbhelp.ExecuteDbTran(connectionString,SQLStringList);
}
public static void ExecuteDbTran(List<string> SQLStringList)
{
dbhelp.ExecuteDbTran(dbhelp.ConnectionStringLocalTransaction, SQLStringList);
}
public static DbDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteReader(connectionString,cmdType,cmdText,commandParameters);
}
public static DbDataReader ExecuteReader( CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteReader(dbhelp.ConnectionStringLocalTransaction, cmdType, cmdText, commandParameters);
}
public static DbDataReader ExecuteReader( string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteReader(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
public static DbDataReader ExecuteReader(string cmdText)
{
return dbhelp.ExecuteReader(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
public static Jobject ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteScalar(connectionString,cmdType,cmdText,commandParameters);
}
public static Jobject ExecuteScalar( CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteScalar(dbhelp.ConnectionStringLocalTransaction, cmdType, cmdText, commandParameters);
}
public static Jobject ExecuteScalar( string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteScalar(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, commandParameters);
}
public static Jobject ExecuteScalar(string cmdText)
{
return dbhelp.ExecuteScalar(dbhelp.ConnectionStringLocalTransaction, CommandType.Text, cmdText, null);
}
public static Jobject ExecuteScalar(DbConnection connection, CommandType cmdType, string cmdText, params DbParameter[] commandParameters)
{
return dbhelp.ExecuteScalar(connection,cmdType,cmdText,commandParameters);
}
public static DataSet ExecuteDataSet(string connectionString, string SQLString)
{
return dbhelp.ExecuteDataSet(connectionString,SQLString);
}
public static DataSet ExecuteDataSet( string SQLString)
{
return dbhelp.ExecuteDataSet(dbhelp.ConnectionStringLocalTransaction, SQLString);
}
}
}
这样只是读取数据库类型的时候反射了一次,性能应该影响不大,这样调用。
这样做也有不好的地方,相比静态反射方式要多写不少代码,每加一个数据库都要写一个相应的Help类。
下面测试一下各个的性能。
测试数据库脚本:
Code
USE [dbrest]
GO
/****** 对象: Table [dbo].[test] 脚本日期: 06/23/2008 14:22:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[test](
[Id] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
测试对象: SqlHelp类 ,静态反射,策略模式
测试方法:
1.用三种方法分别向数据库插入10W条数据(注意:这个辅助类不适合处理大量数据插入的任务,这里仅是测试,真实项目中不要这么做)。
2.用三种方法分别向数据库插入10条数据。
测试代码:
SqlHelp:
Code
Stopwatch sp = Stopwatch.StartNew();
SqlParameter[] sqlparm ={ new SqlParameter("@name",SqlDbType.NVarChar, 50) };
for (int i = 0; i < 100000; i++)
{
sqlparm[0].Value = "测试" + i.ToString() + "~~";
Jdpc.SqlHelper.ExecuteNonQuery("insert into test ([name]) values (@name)", sqlparm);
}
sp.Stop();
Response.Write("SqlHelp插入10W条数据,程序运行耗时:"+
静态反射:
Code
Stopwatch sp = Stopwatch.StartNew();
JDParameter jdp = new JDParameter();
jdp.Add("@name", DbType.String, 50);
for (int i = 0; i < 100000; i++)
{
jdp [0].Value = "测试" + i.ToString() + "~~";
Datahelper.ExecuteNonQuery("insert into test ([name]) values (@name)", jdp.Dbparams);
}
sp.Stop();
Response.Write("静态反射插入10W条数据,程序运行耗时:"+
策略模式:
Code
Stopwatch sp = Stopwatch.StartNew();
DbParameter[] sqlparm ={ new DBContext.AddParameter("@name",SqlDbType.NVarChar, 50) };
for (int i = 0; i < 100000; i++)
{
sqlparm[0].Value = "测试" + i.ToString() + "~~";
DBContext.ExecuteNonQuery("insert into test ([name]) values (@name)", jdp.Dbparams);
}
sp.Stop();
Response.Write("插入10W条数据,程序运行耗时:"+
测试结果:
SqlHelper第一次 插入10W条数据,程序运行耗时:
159888488663
SqlHelper第二次 插入10W条数据,程序运行耗时:
160687917724
SqlHelper第三次 插入10W条数据,程序运行耗时:
154527187035
策略模式第一次 插入10W条数据,程序运行耗时:
158770717499
策略模式第二次 插入10W条数据,程序运行耗时:
160742563763
策略模式第三次 插入10W条数据,程序运行耗时:
154720465316
静态反射第一次 插入10W条数据,程序运行耗时:
229434867004
静态反射第二次 插入10W条数据,程序运行耗时:
214389131899
静态反射第三次 插入10W条数据,程序运行耗时:
210254611603
由此可见,策略模式的方式还是不错的,与Sqlhelper相比几乎没有性能损失,静态反射方式则性能损失明显。这么说我应该选择策略模式作为最后的解决方案了?不一定,刚才说了,这个辅助类不适合处理大量数据插入的任务,这个测试仅仅是为了看看三种方式处理大数据的性能,现实中遇到这样的任务早用其他方式优化了。所以这样的方式在现实中的使用率基本为0,靠这个测试来下结论是没有意义的。下面看插入10条数据的测试,这个才是比较常见的任务~
测试结果:
SqlHelper第1次 插入10条数据,程序运行耗时:
24282828
SqlHelper第2次 插入10条数据,程序运行耗时:
13098557
SqlHelper第3次 插入10条数据,程序运行耗时:
13076609
SqlHelper第4次 插入10条数据,程序运行耗时:
15343301
SqlHelper第5次 插入10条数据,程序运行耗时:
13700515
SqlHelper第6次 插入10条数据,程序运行耗时:
14315018
SqlHelper第7次 插入10条数据,程序运行耗时:
13333270
SqlHelper第8次 插入10条数据,程序运行耗时:
18766929
SqlHelper第9次 插入10条数据,程序运行耗时:
13543373
SqlHelper第10次 插入10条数据,程序运行耗时:
14285184
SqlHelper第11次 插入10条数据,程序运行耗时:
13966000
SqlHelper第12次 插入10条数据,程序运行耗时:
16312366
SqlHelper第13次 插入10条数据,程序运行耗时:
16657053
SqlHelper第14次 插入10条数据,程序运行耗时:
16684147
SqlHelper第15次 插入10条数据,程序运行耗时:
13948950
策略模式第1次 插入10条数据,程序运行耗时:
28917960
策略模式第2次 插入10条数据,程序运行耗时:
13024157
策略模式第3次 插入10条数据,程序运行耗时:
12921475
策略模式第4次 插入10条数据,程序运行耗时:
15099535
策略模式第5次 插入10条数据,程序运行耗时:
13556757
策略模式第6次 插入10条数据,程序运行耗时:
13824979
策略模式第7次 插入10条数据,程序运行耗时:
14306067
策略模式第8次 插入10条数据,程序运行耗时:
16415564
策略模式第9次 插入10条数据,程序运行耗时:
13572702
策略模式第10次 插入10条数据,程序运行耗时:
13571828
策略模式第11次 插入10条数据,程序运行耗时:
13798897
策略模式第12次 插入10条数据,程序运行耗时:
14894078
策略模式第13次 插入10条数据,程序运行耗时:
13607394
策略模式第14次 插入10条数据,程序运行耗时:
13967062
策略模式第15次 插入10条数据,程序运行耗时:
14625442
静态反射第1次 插入10条数据,程序运行耗时:
21599266
静态反射第2次 插入10条数据,程序运行耗时:
16478487
静态反射第3次 插入10条数据,程序运行耗时:
14593340
静态反射第4次 插入10条数据,程序运行耗时:
15976455
静态反射第5次 插入10条数据,程序运行耗时:
13981077
静态反射第6次 插入10条数据,程序运行耗时:
16031862
静态反射第7次 插入10条数据,程序运行耗时:
19986908
静态反射第8次 插入10条数据,程序运行耗时:
16614291
静态反射第9次 插入10条数据,程序运行耗时:
26047964
静态反射第10次 插入10条数据,程序运行耗时:
15660924
静态反射第11次 插入10条数据,程序运行耗时:
18112492
静态反射第12次 插入10条数据,程序运行耗时:
15651340
静态反射第13次 插入10条数据,程序运行耗时:
14652823
静态反射第14次 插入10条数据,程序运行耗时:
17635581
静态反射第15次 插入10条数据,程序运行耗时:
18890318
大家可以看到,结果差不多。这下不好选择了,使用哪个呢?我是还没想好。
两个方式的代码在这里下载~
注:代码是两天前传的,这里贴的代码是后来修改过的,改了几个类名,没其他变化~