虽然现在有很多ORM ,但有时候我们可能只是需要简单的数据操作,于是写了一个数据库通用访问组件。其实这个最开始连接口都没有,到最后逐步完善.虽然是普通的数据访问,但是我们还是要来实现一些可插拔特性和工厂模式.
首先来定义接口
class="brush:csharp;collapse:true;;gutter:true;">using System;
using System.Collections.Generic;
using System.Data;
using System.Collections;
using System.Data.Common;
namespace FYJ.Data
{
public enum DbHelperType : int
{
Other = 0,
SqlServer = 1,
Oracle = 2,
OleDb = 3,
MySql = 4,
SqlLite = 5,
Odbc = 6
}
/// <summary>
/// 功能:数据接口
/// 作者:fangyj
/// 创建日期:2012-07-15
/// 修改日期:2013-08-11
/// </summary>
public interface IDbHelper
{
#region 执行
/// <summary>
/// 执行一条sql语句
/// </summary>
/// <param name="sql"></param>
/// <param name="parms"></param>
/// <returns></returns>
int ExecuteSql(string sql, params IDataParameter[] parms);
/// <summary>
/// 执行一条sql语句
/// </summary>
/// <param name="parms"></param>
/// <param name="sql"></param>
/// <returns></returns>
int ExecuteSql(IEnumerable<IDataParameter> parms, string sql);
/// <summary>
/// 根据IDataParameter 自动生成sql语句并执行
/// </summary>
/// <param name="tableName">表明</param>
/// <param name="pkName">主键名</param>
/// <param name="iaAdd">是否插入语句,否则为修改</param>
/// <param name="list"></param>
/// <returns></returns>
int ExecuteSql(string tableName, string pkName, bool iaAdd, IEnumerable<IDataParameter> parms);
/// <summary>
/// 执行存储过程 返回DataSet
/// </summary>
/// <param name="parms">存储过程参数</param>
/// <param name="storedProcName">存储过程名</param>
/// <returns></returns>
DataSet RunProcedure(IEnumerable<IDataParameter> parms, string storedProcName);
/// <summary>
/// 执行存储过程 返回DataSet
/// </summary>
/// <param name="storedProcName">存储过程名</param>
/// <param name="parms">存储过程参数</param>
/// <returns></returns>
DataSet RunProcedure(string storedProcName, params IDataParameter[] parms);
/// <summary>
/// 执行存储过程
/// </summary>
/// <param name="storedProcName">存储过程名</param>
/// <param name="dic">以存储过程参数名为key 参数值为value</param>
/// <returns></returns>
DataSet RunProcedure(string storedProcName, Dictionary<String, object> dic);
/// <summary>
/// 执行存储过程 返回整数值 @RETURN_VALUE
/// </summary>
/// <param name="storedProcName"></param>
/// <param name="dic"></param>
/// <returns></returns>
int ExecuteProcedure(string storedProcName, Dictionary<String, object> dic);
/// <summary>
/// 执行存储过程 返回整数值 @RETURN_VALUE
/// </summary>
/// <param name="parms"></param>
/// <param name="storedProcName"></param>
/// <returns></returns>
int ExecuteProcedure(IEnumerable<IDataParameter> parms, string storedProcName);
/// <summary>
/// 执行存储过程 返回整数值 @RETURN_VALUE
/// </summary>
/// <param name="storedProcName"></param>
/// <param name="parms"></param>
/// <returns></returns>
int ExecuteProcedure(string storedProcName, params IDataParameter[] parms);
#endregion
#region 查询
/// <summary>
/// 获取DataSet
/// </summary>
/// <param name="parms"></param>
/// <param name="sql"></param>
/// <returns></returns>
DataSet GetDataSet(IEnumerable<IDataParameter> parms, string sql);
/// <summary>
/// 获取DataSet
/// </summary>
/// <param name="sql"></param>
/// <param name="parms"></param>
/// <returns></returns>
DataSet GetDataSet(string sql, params IDataParameter[] parms);
/// <summary>
/// 获取查询的数据列表 IDataParameter参数前缀@ :或者不加都会自动修正 currentPage设置为0表示不返回数据 currentPage为null则返回所有数据
/// count传递null表示不返回总数
/// </summary>
/// <param name="count">是否返回总记录条数 </param>
/// <param name="tableName">表或视图名 </param>
/// <param name="accessProperty">要访问的列</param>
/// <param name="where">查询条件</param>
/// <param name="orderProperty">排序</param>
/// <param name="currentPage">当前页</param>
/// <param name="pageSize">每页显示条数</param>
/// <returns></returns>
DataTable GetDataTable(ref long? count, string tableName, string order, string[] accessProperty = null, string where = null, int currentPage = 1, int pageSize = 20);
/// <summary>
/// 获取DataTable 该值为DataSet的第一张表
/// </summary>
/// <param name="parms"></param>
/// <param name="sql"></param>
/// <returns></returns>
DataTable GetDataTable(IEnumerable<IDataParameter> parms, string sql);
/// <summary>
/// 获取DataTable 该值为DataSet的第一张表
/// </summary>
/// <param name="sql"></param>
/// <param name="parms"></param>
/// <returns></returns>
DataTable GetDataTable(string sql, params IDataParameter[] parms);
/// <summary>
/// 获取前max行数据 如果max小于1 则返回所有行
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="max"></param>
/// <returns></returns>
DataTable GetDataTable(string tableName, long max);
/// <summary>
/// 获取第一行第一列object值
/// </summary>
/// <param name="parms"></param>
/// <param name="sql"></param>
/// <returns></returns>
object GetObject(IEnumerable<IDataParameter> parms, string sql);
object GetObject(string sql, params IDataParameter[] parms);
string GetString(IEnumerable<IDataParameter> parms, string sql);
string GetString(string sql, params IDataParameter[] parms);
long GetLong(IEnumerable<IDataParameter> parms, string sql);
long GetLong(string sql, params IDataParameter[] parms);
double GetDouble(IEnumerable<IDataParameter> parms, string sql);
double GetDouble(string sql, params IDataParameter[] parms);
int GetInt(IEnumerable<IDataParameter> parms, string sql);
int GetInt(string sql, params IDataParameter[] parms);
bool GetBoolean(IEnumerable<IDataParameter> parms, string sql);
bool GetBoolean(string sql, params IDataParameter[] parms);
bool Exists(IEnumerable<IDataParameter> parms, string sql);
bool Exists(string sql, params IDataParameter[] parms);
/// <summary>
/// 表是否存在
/// </summary>
/// <param name="tableName"></param>
/// <returns></returns>
bool ExistsTable(string tableName);
/// <summary>
/// 获取当前数据库所有表
/// </summary>
/// <returns></returns>
List<string> GetTables();
#endregion
/// <summary>
/// 创建DbParameter对象
/// </summary>
/// <param name="parameterName"></param>
/// <param name="parameterValue"></param>
/// <param name="direction"></param>
/// <returns></returns>
DbParameter CreateParameter(string parameterName = null, object parameterValue = null, ParameterDirection? direction = null);
#region 属性
/// <summary>
/// 获取DbProviderFactory对象
/// </summary>
/// <returns></returns>
DbProviderFactory DbProviderFactoryInstance { get; set; }
/// <summary>
/// 获取连接对象
/// </summary>
/// <returns></returns>
DbConnection DbConnectionInstance { get; set; }
/// <summary>
/// 获取数据类型枚举
/// </summary>
/// <returns></returns>
DbHelperType DbHelperTypeEnum { get; }
DbTransaction Tran { get; }
#endregion
/// <summary>
/// 开始事务
/// </summary>
void BeginTran();
/// <summary>
/// 提交事务
/// </summary>
void Commit();
/// <summary>
/// 回滚
/// </summary>
void Rollback();
/// <summary>
/// 打开连接
/// </summary>
void OpenConnection();
/// <summary>
/// 关闭连接
/// </summary>
void CloseConnection();
/// <summary>
/// 测试数据库是否可以打开
/// </summary>
/// <returns></returns>
bool TestCanConnectionOpen();
}
}
这个接口是不是有点多。。。
我们没有使用config文件里面的appSettings和connectionStrings来配置,因为需要扩展更多的属性.于是自己写section吧,当然也可以自己写xml,感觉写xml还简单些
以下是配置文件
<configSections>
<section name="DbHelperSettings" type="FYJ.Data.Config.DbHelperSection, FYJ.Data" />
</configSections>
<DbHelperSettings>
<DbHelperSetting name="hotel" type="FYJ.Data.DbHelper,FYJ.Data" providerName="System.Data.SqlClient" connectionString="server=.;database=db_hotel;uid=xx;pwd=xx" isEncrypt="false" encryptType="FYJ.Data.DbEncrypt,FYJ.Data">
</DbHelperSetting>
</DbHelperSettings>
<appSettings>
可以看到有很多属性,name是唯一的id不能重复,type是FYJ.Data.IDbHelper接口的实现,isEncrypt表示是否加密连接字符串,encryptType是实现了FYJ.Data.IDbEncrypt的解密类,该接口就只有一个方法 string Decrypt(string text);返回解密后的字符串
下面我们来看工厂类
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Data.Common;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
namespace FYJ.Data
{
/// <summary>
/// 工厂类,无法继承该类
/// </summary>
public sealed class DbFactory
{
private static Dictionary<string, IDbHelper> dbs = new Dictionary<string, IDbHelper>();
/// <summary>
/// 根据配置节点主键名构造IDbHelper对象
/// </summary>
/// <param name="configName"></param>
/// <returns></returns>
public static IDbHelper CreateIDbHelper(string configName)
{
var items = (ConfigurationManager.GetSection("DbHelperSettings") as FYJ.Data.Config.DbHelperSection).Items;
foreach (FYJ.Data.Config.DbHelperElement item in items)
{
if (item.Name == configName)
{
Type t = Type.GetType(item.Type);
IDbHelper db = (IDbHelper)Activator.CreateInstance(t);
DbProviderFactory factory = null;
string connectionString = item.ConnectionString;
if (item.IsEncrypt == true)
{
IDbEncrypt encrypt = (IDbEncrypt)Activator.CreateInstance(Type.GetType(item.EncryptType));
connectionString = encrypt.Decrypt(connectionString);
}
if (item.ProviderName.StartsWith("MySql.Data", StringComparison.CurrentCultureIgnoreCase))
{
object obj = Assembly.Load("MySql.Data").CreateInstance("MySql.Data.MySqlClient.MySqlClientFactory");
factory = (DbProviderFactory)obj;
}
else if (item.ProviderName.StartsWith("System.Data.SQLite", StringComparison.CurrentCultureIgnoreCase))
{
object obj = Assembly.Load("System.Data.SQLite").CreateInstance("System.Data.SQLite.SQLiteFactory");
factory = (DbProviderFactory)obj;
String dbFileName = Regex.Match(connectionString, "data\\s*source\\s*=\\s*(.*)").Groups[1].Value;
if (!File.Exists(dbFileName))
{
connectionString = "data source=" + Path.Combine(AppDomain.CurrentDomain.BaseDirectory, dbFileName);
}
}
else
{
factory = DbProviderFactories.GetFactory(item.ProviderName);
}
db.DbProviderFactoryInstance = factory;
db.DbConnectionInstance = factory.CreateConnection();
db.DbConnectionInstance.ConnectionString = connectionString;
return db;
}
}
throw new Exception("名为" + configName + "的数据配置不存在");
}
/// <summary>
/// 根据配置节点主键名构造IDbHelper对象
/// </summary>
/// <param name="configName"></param>
/// <returns></returns>
public static IDbHelper GetIDbHelper(string configName)
{
if (!dbs.ContainsKey(configName))
{
dbs.Add(configName, CreateIDbHelper(configName));
}
return dbs[configName];
}
}
}
CreateIDbHelper 方法是创建一个实现FYJ.Data.IDbHelper接口的实例,相应GetIDbHelper方法是得到一个静态的全局实例,并且会自动修正SQLite的连接字符串
由于代码贴得有点多,所以留在下面一篇
本文为个人原创,欢迎转载但请以超链接的形式注明出处哦。