厚积薄发,丰富的公用类库积累,助你高效进行系统开发(3)----数据库相关操作

在前面随笔《厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)》和《厚积薄发,丰富的公用类库积累,助你高效进行系统开发(2)》,介绍了公用类库的包含的内容以及相关使用说明,本文将继续把在整理帮助文档成CHM过程中,完成的类库使用说明逐步放送,一是使得大家对类库的功能及使用有一个大致的了解,并能够在实际中应用,或者能够和大家在这方面继续探讨,逐步改进和完善。
1、 Access数据库文件操作辅助类JetAccessUtil
**实现效果 **
1)本辅助类主要是用来方便实现Access数据库文件操作,包括新建Access数据库(可含密码)、压缩数据库、设置数据库密码、列出数据库表、列出数据库表字段等常用的Access数据库文件操作的实现。

实现代码
1)辅助类库JetAccessUtil的相关方法定义

/// <summary>    
/// 新建带密码的空Access 2000 数据库    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <param name="password">数据库密码</param>    
/// <returns>字符0为操作成功,否则为失败异常消息。</returns>    
public static string CreateMDB(string mdbFilePath, string password)    
   
/// <summary>    
/// 新建空的Access数据库    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <returns>字符0为操作成功,否则为失败异常消息。</returns>    
public static string CreateMDB(string mdbFilePath)    
   
/// <summary>    
/// 压缩带密码Access数据库    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <param name="password">数据库密码</param>    
/// <returns>字符0为操作成功,否则为失败异常消息。</returns>    
public static string CompactMDB(string mdbFilePath, string password)    
   
/// <summary>    
/// 压缩没有带密码Access数据库    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <returns>字符0为操作成功,否则为失败异常消息。</returns>    
public static string CompactMDB(string mdbFilePath)    
   
/// <summary>    
/// 设置Access数据库的访问密码    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <param name="oldPwd">旧密码</param>    
/// <param name="newPwd">新密码</param>    
/// <returns>字符0为操作成功,否则为失败异常消息。</returns>    
public static string SetMDBPassword(string mdbFilePath, string oldPwd, string newPwd)    
   
/// <summary>    
/// 列出Access 2000 数据库的表名称    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <param name="password">数据库密码</param>    
/// <returns></returns>    
public static List<string> ListTables(string mdbFilePath, string password)    
   
/// <summary>    
/// 列出Access2000数据库的表字段    
/// </summary>    
/// <param name="mdbFilePath">数据库文件路径</param>    
/// <param name="password">数据库密码</param>    
/// <param name="tableName">表名称</param>    
/// <returns>返回字段名称和对应类型的字典数据</returns>    
public static Dictionary<string, string> ListColumns(string mdbFilePath, string password, string tableName) 

2)辅助类库的使用例子。

string fileNoPass = Path.Combine(Path.GetTempPath(), "EmptyNoPass.mdb");    
string filePass = Path.Combine(Path.GetTempPath(), "EmptyWithPass.mdb");    
   
//创建不带密码的空数据库    
JetAccessUtil.CreateMDB(fileNoPass);    
//创建带密码的空数据库    
JetAccessUtil.CreateMDB(filePass, "wuhuacong@163.com");    
   
//压缩不带密码的数据库    
JetAccessUtil.CompactMDB(fileNoPass);    
//压缩带密码的数据库    
JetAccessUtil.CompactMDB(filePass, "wuhuacong@163.com");    
   
//重新设置数据库的密码    
JetAccessUtil.SetMDBPassword(filePass, "wuhuacong@163.com", "6966254");    
//列出数据库的表名称    
List<string> tableNameList = JetAccessUtil.ListTables(filePass, "6966254");    
string strNameList = "";    
foreach (string name in tableNameList)    
{    
    strNameList += string.Format(",{0}", name);    
}    
if (!string.IsNullOrEmpty(strNameList))    
{    
    MessageUtil.ShowTips(strNameList);    
}    
  
Process.Start(Path.GetTempPath());  

** 2、常用的Access数据库Sql操作辅助类库 OleDbHelper**
** 实现效果**
1)本辅助类主要是用来方便实现对Access数据库文件的Sql访问,包括测试连接、执行Sql、获取返回数据集等操作。
2)辅助类库构造对象的时候,只需要传入Access数据库文件,即可对其进行相关的Sql操作,简化对Access数据库执行脚本的操作。

**实现代码 **
1)辅助类OleDbHelper提供的函数列表如下所示。

/// <summary>    
/// 常用的Access数据库Sql操作辅助类库    
/// </summary>    
public class OleDbHelper    
{    
    /// <summary>    
    /// 构造函数    
    /// </summary>    
    /// <param name="accessFilePath"></param>    
    public OleDbHelper(string accessFilePath)    
   
    /// <summary>    
    /// 测试数据库是否正常连接    
    /// </summary>    
    /// <returns></returns>    
    public bool TestConnection()    
   
    /// <summary>    
    /// 执行Sql,并返回成功的数量    
    /// </summary>    
    /// <param name="sqlList">待执行的Sql列表</param>    
    /// <returns></returns>    
    public int ExecuteNonQuery(List<string> sqlList)    
   
    /// <summary>    
    /// 执行无返回值的语句,成功返回True,否则False    
    /// </summary>    
    /// <param name="sql">待执行的Sql</param>    
    /// <returns></returns>    
    public bool ExecuteNoQuery(string sql)    
   
    /// <summary>    
    /// 执行单返回值的语句    
    /// </summary>    
    /// <param name="sql">待执行的Sql</param>    
    /// <returns></returns>    
    public object ExecuteScalar(string sql)    
   
    /// <summary>    
    /// 执行Sql,并返回IDataReader对象。    
    /// </summary>    
    /// <param name="sql">待执行的Sql</param>    
    /// <returns></returns>    
    public IDataReader ExecuteReader(string sql)    
   
    /// <summary>    
    /// 执行Sql并返回DataSet集合    
    /// </summary>    
    /// <param name="sql">待执行的Sql</param>    
    /// <returns></returns>    
    public DataSet ExecuteDataSet(string sql)    
}      

2)实现操作例子如下所示。

string access = @"C:\Orderwater.mdb";    
List<string> tableNameList = JetAccessUtil.ListTables(access, "");    
OleDbHelper helper = new OleDbHelper(access);    
   
foreach(string tableName in tableNameList)    
{    
    string sql = string.Format("Select * from {0} ", tableName);    
    DataSet ds = helper.ExecuteDataSet(sql);    
    if (ds.Tables[0].Rows.Count > 0)    
    {    
        MessageUtil.ShowTips(string.Format("tableName:{0} RowCount:{1}", tableName, ds.Tables[0].Rows.Count));    
    }   
}    

**3、根据各种不同数据库生成不同分页语句的辅助类 PagerHelper **
实现效果
1)本辅助类主要是用来方便根据各种条件,生成不同的分页语句,且支持Oracle、SqlServer、Access、MySql数据库分页语句的生成。

2)辅助类可以根据表名、查询字段列表、排序字段、分页数量、分页页码、降序升序、查询条件等条件组合成一条完整的分页语句,并且支持获取数量和列表两种语句接口,非常方便用于数据的分页处理。


实现代码:
1)使用例子说明。通过构造PageHelper类,并传入表名、查询字段、排序字段、页面大小、当前页码、降序升序、查询条件等参数,可以生成基于Oracle、SqlServer、Access、MySql数据库的分页语句。然后通过具体查询总数语句、查询列表语句可以完成获取指定数据列表的显示,由于分页是基于一页一页的获取,这样提高了数据分页的效率。

/// <summary>
/// 通过自己组装分页语句        
/// </summary>        
/// <param name="where"></param>        
/// <param name="pagerInfo"></param>        
/// <returns></returns>        
private DataTable DirectLoadData(string where, PagerInfo pagerInfo)        
{        
    DataTable dt = null;        
    PagerHelper helper = new PagerHelper("All_Customer", "*", "ID", pagerInfo.PageSize, pagerInfo.CurrenetPageIndex, true, where);        
    string countSql = helper.GetPagingSql(DatabaseType.SqlServer, true);        
    string dataSql = helper.GetPagingSql(DatabaseType.SqlServer, false);        
       
    string value = SqlValueList(countSql);        
    pagerInfo.RecordCount = Convert.ToInt32(value);        
       
    dt = SqlTable(dataSql);        
       
    return dt;        
}  

4、 查询条件组合辅助类 SearchCondition
**实现效果 **
1)本辅助类主要是用来方便实现对查询表单的各种条件进行组合,快速拼接Sql语句的操作,类库可用于Web项目和Winform项目的查询列表拼接语句。
2)使用场景: 在查询列表页面中,一般有好几个条件, 用户进行查询时候,需要根据这几个条件进行过滤查询.但在组装这些过滤条件的时候,代码比较烦琐臃肿,本组件代码为解决该问题而设计。

3)使用目的: 1.减少对参数非空的条件判断 2. 支持SqlServer、Oracle、Access、MySql数据访问的Sql语句的生成,根据不同数据库的一些特点差异,生成对应的语句. 3. 减少拼接语句的代码并减少出错的几率 4.构造Sql语句或者参数化条件更加易读。
4) SearchCondition辅助类的类图如下所示,其中SearchCondtion是语句操作对象类,SearchInfo是语句的条件实体类,SqlOperator是各种查询条件的枚举对象,方便操作并减少输入字符条件的出错。



**实现代码 **
1)生成Sql语句
如有几个字段,需要根据不同的字段进行过滤,想生成的SQL语句如下:

Where (1=1) AND AA2 Like '%AA2Value%' AND AA6 >= 'Value6' AND AA7 <= 'value7'
AND AA3 = 'Value3' AND AA4 < 'Value4' AND AA5 > 'Value5' AND AA <> '1'

2)与普通做法的比较。下面我们比较一下使用该控件和不使用在列表查询页面中的代码,可以看出使用了控件后的代码大大较少了,并且可读性也增强了

private string GetCondition()    
{    
    SearchCondition search = new SearchCondition();    
    search.AddCondition("GroupID", this.ddlUserGroup.SelectedValue, SqlOperator.Equal, true)//班组ID    
          .AddCondition("DealGroupName", this.ddlDealGroup.SelectedValue, SqlOperator.Equal, true)/*消缺单位*/   
          .AddCondition("VisioStationID", this.ddlStation.SelectedValue, SqlOperator.Like, true)//变电站    
          .AddCondition("VisioImageID", this.ddlLine.SelectedValue, SqlOperator.Like, true)/*馈线*/   
          .AddCondition("BugNo", this.txtBugNo.Text.Trim(), SqlOperator.Like, true)/*编号*/   
          .AddCondition("Finder", this.ddlFindUser.SelectedValue, SqlOperator.Like, true)/*发现人*/   
          .AddCondition("CheckUser", this.ddlCheckUser.SelectedValue, SqlOperator.Like, true)//验收人    
          .AddCondition("DeviceBug.BugType", this.ddlBugType.SelectedValue, SqlOperator.Equal, true)//缺陷类别    
          .AddCondition("CurrentState", this.ddlCurrentState.SelectedValue, SqlOperator.Equal, true)//处理状态    
          .AddCondition("FindDate", this.txtFindBeginDate.Text.Trim(), SqlOperator.MoreThanOrEqual, true)//发现日期    
          .AddCondition("FindDate", this.txtFindEndDate.Text.Trim(), SqlOperator.LessThanOrEqual, true)//发现日期    
          .AddCondition("EndDate", this.txtEndBeginDate.Text.Trim(), SqlOperator.MoreThanOrEqual, true)//消缺日期    
          .AddCondition("EndDate", this.txtEndEndDate.Text.Trim(), SqlOperator.LessThanOrEqual, true);//消缺日期    
   
    return search.BuildConditionSql(DatabaseType.SqlServer);    
}    

普通做法,不使用控件在构造列表查询的语句的函数代码则比较繁琐复杂,如下所示。

private string GetCondition()    
{    
  string condition = "";    
  if ( this.ddlUserGroup.SelectedValue != "0")    
  {    
      condition += string.Format( " GroupID = {0}" , this.ddlUserGroup.SelectedValue.ToString() );    
  }    

  //消缺单位    
  if ( this.ddlDealGroup.SelectedValue != "0")    
  {    
      if (condition == "")    
      {    
          condition += string.Format( " DealGroupName = '{0}'" , this.ddlDealGroup.SelectedItem.Text );    
      }    
      else   
      {    
          condition += string.Format( " And DealGroupName = '{0}'" , this.ddlDealGroup.SelectedItem.Text );    
      }    
  }    

      
  if (this.txtStation.Text.Trim() != "")    
  {    
      if (condition == "")    
      {    
          condition += string.Format(" Station like '%{0}%'",this.txtStation.Text.Trim() );    
      }    
      else   
      {    
          condition += string.Format(" And Station like '%{0}%' ",this.txtStation.Text.Trim() );    
      }    
  }   
..............(很多类似的代码)

**5、转换IDataReader字段对象的格式辅助类 SmartDataReader **
实现效果
1)本辅助类主要是用来方便转换IDataReader字段对象的格式辅助类,可以转换有默认值、可空类型的字段数据。

2)在使用数据库返回对象IDataReader的时候,我们需要判断数据库字段是否为可空类型,并赋予空字段默认值,或者转换为可空类型数据,使用该辅助类,可以简化繁琐的数据库字段转换操作,是数据库字段转换必备的辅助类。

实现代码
1)辅助类SmartDataReader的转换数据格式的操作例子如下。

/// <summary>    
/// 通用获取集合对象方法    
/// </summary>    
/// <param name="sql">查询的Sql语句</param>    
/// <param name="paramList">参数列表,如果没有则为null</param>    
/// <returns></returns>    
private List<T> GetList(string sql, IDbDataParameter[] paramList)    
{    
  T entity = null;    
  List<T> list = new List<T>();    

  Database db = DatabaseFactory.CreateDatabase();    
  DbCommand command = db.GetSqlStringCommand(sql);    
  if (paramList != null)    
  {    
      command.Parameters.AddRange(paramList);    
  }    

  using (IDataReader dr = db.ExecuteReader(command))    
  {    
      while (dr.Read())    
      {    
          entity = DataReaderToEntity(dr);    

          list.Add(entity);    
      }    
  }    
  return list;    
}    
   
/// <summary>    
/// 将DataReader的属性值转化为实体类的属性值,返回实体类    
/// </summary>    
/// <param name="dr">有效的DataReader对象</param>    
/// <returns>实体类对象</returns>    
protected ItemDetailInfo DataReaderToEntity(IDataReader dataReader)    
{    
    ItemDetailInfo itemDetailInfo = new ItemDetailInfo();    
    SmartDataReader reader = new SmartDataReader(dataReader);    
        
    itemDetailInfo.ID = reader.GetInt32("ID");    
    itemDetailInfo.ItemNo = reader.GetString("ItemNo");    
    itemDetailInfo.ItemName = reader.GetString("ItemName");    
    itemDetailInfo.Manufacture = reader.GetString("Manufacture");    
    itemDetailInfo.MapNo = reader.GetString("MapNo");    
    itemDetailInfo.Specification = reader.GetString("Specification");    
    itemDetailInfo.Material = reader.GetString("Material");    
    itemDetailInfo.ItemBigType = reader.GetString("ItemBigType");    
    itemDetailInfo.ItemType = reader.GetString("ItemType");    
    itemDetailInfo.Unit = reader.GetString("Unit");    
    itemDetailInfo.Price = reader.GetDecimal("Price");    
    itemDetailInfo.Source = reader.GetString("Source");    
    itemDetailInfo.StoragePos = reader.GetString("StoragePos");    
    itemDetailInfo.UsagePos = reader.GetString("UsagePos");    
    itemDetailInfo.Note = reader.GetString("Note");    
    itemDetailInfo.WareHouse = reader.GetString("WareHouse");    
    itemDetailInfo.Dept = reader.GetString("Dept");    
        
    return itemDetailInfo;    
} 

2)辅助类SmartDataReader提供了各种类型的数据转换函数,如Int32、Int16、Decimal、Float、DateTime等数据类型的格式转换,每个格式提供了几种方式的处理,如对Int类型的数据转换,其封装的函数实现如下所示。

/// <summary>    
/// 转换为Int类型数据    
/// </summary>    
public int GetInt32(string column)    
{    
    return GetInt32(column, 0);    
}    
   
/// <summary>    
/// 转换为Int类型数据    
/// </summary>    
public int GetInt32(string column, int defaultIfNull)    
{    
    int data = (reader.IsDBNull(reader.GetOrdinal(column))) ? (int)defaultIfNull : int.Parse(reader[column].ToString());    
    return data;    
}    
   
/// <summary>    
/// 转换为Int类型数据    
/// </summary>    
public int? GetInt32Nullable(string column)    
{    
    int? data = (reader.IsDBNull(reader.GetOrdinal(column))) ? (int?)null : int.Parse(reader[column].ToString());    
    return data;   
}  

**6、OSql命令操作函数辅助类 SqlScriptHelper **
实现效果
1)本辅助类主要是 OSql命令操作函数(可用于安装程序的时候数据库脚本执行)。

2)本辅助类库通常用在SqlServer数据库脚本执行,附加、分离、备份、恢复数据库等操作。

实现代码
1)主要的类库函数如下所示。

/// <summary>    
/// 本地执行SQL脚本    
/// </summary>    
/// <param name="path">脚本文件路径全名</param>    
public static void DoSQL(string path)    
   
/// <summary>    
/// 执行SQL脚本    
/// </summary>    
/// <param name="path">脚本文件路径全名</param>    
/// <param name="userID">数据库登录ID</param>    
/// <param name="password">数据库登录密码</param>    
/// <param name="server">数据库服务器地址</param>    
public static void DoSQL(string path, string userID, string password, string server)    
   
/// <summary>    
/// 后台执行DOS文件    
/// </summary>    
/// <param name="fileName">文件名(包含路径)</param>    
/// <param name="argument">运行参数</param>    
/// <param name="hidden">是否隐藏窗口</param>    
public static void RunDos(string fileName, string argument, bool hidden)    
   
/// <summary>    
/// 在运行脚本之前把脚本中的数据库名称替换成安装界面输入的数据库名称    
/// </summary>    
/// <param name="filePath">脚本文件名</param>    
/// <param name="oldDBName">原有的数据库名称</param>    
/// <param name="newDBName">新的数据库名称</param>    
public static void ReplaceDBName(string filePath, string oldDBName, string newDBName)    
   
/// <summary>    
/// 附加SqlServer数据库    
/// </summary>    
public bool AttachDB(string connectionString, string dataBaseName, string dataBase_MDF, string dataBase_LDF)    
   
/// <summary>    
/// 分离SqlServer数据库    
/// </summary>    
public bool DetachDB(string connectionString, string dataBaseName)    
   
/// <summary>    
/// 还原数据库    
/// </summary>    
public bool RestoreDataBase(string connectionString, string dataBaseName, string DataBaseOfBackupPath, string DataBaseOfBackupName)    
   
/// <summary>    
/// 备份SqlServer数据库    
/// </summary>    
public bool BackupDataBase(string connectionString, string dataBaseName, string DataBaseOfBackupPath, string DataBaseOfBackupName)   

2)安装执行数据库脚本的操作例子如下所示。

string sqlFilePath = physicalRoot + "Hotel.sql";    
SqlScriptHelper.ReplaceDBName(sqlFilePath, "Hotel_Database", EdnmsDb.Database);    

if (!string.IsNullOrEmpty(EdnmsDb.UserId) && !string.IsNullOrEmpty(EdnmsDb.Password))    
{    
 SqlScriptHelper.DoSQL(sqlFilePath, EdnmsDb.UserId, EdnmsDb.Password, EdnmsDb.Server);    
}    
else   
{    
 SqlScriptHelper.DoSQL(sqlFilePath, EdnmsDb.Server);    
}  

基于时间和篇幅考虑,下次继续介绍相关的类库使用,另外提一下,整个系列的CHM文档也在同步整理中,我们来看看目前进度的完成的CHM文件情况。


再次感谢大家的支持和鼓励。
CHM帮助文档持续更新中,统一下载地址是: http://www.iqidi.com/download/commonshelp.rar

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容