自然框架之数据访问

数据库 SQL Server
笔者从2004年开始用自己的数据访问,一直到现在,经历过改版,也增加了不少的功能。写下这篇文章的目的整理思路、整理代码;另外一个,是告诉我们【自然框架】的数据访问 —— 再小的类库也需要设计。

以前也写过几篇关于数据访问的,这里是***的总结。麻雀虽小五脏俱全,数据访问也许不起眼,但是也要好好的设计一翻。从2004年开始用自己的数据访问,一直到现在,经历过两次大的改版,随着需求的变化,也增加了不少的功能,小修小改那就更多了。目的就是能够让自己更轻松一点。整理思路、整理代码,写点东西,一个是给自己留个脚印;另外一个,说不定也许能够给大家帮个小忙。

目标:

简单、好用、易扩展、稳定、性能。

特点:

  1. 基于ADO.net 2.0 编写,理论上可以支持多种数据库,目前测试了SQL Server 和Access,一位朋友帮忙测试了MySQL。Orcale等其他数据库没有测试过。
  2. 使用非常简单。
  3. 支持事务、存储过程、参数化SQL等。
  4. 对存储过程的参数进行封装,更便于操作和更换数据库。
  5. 如果运行是出现异常,可以把异常信息、出错的SQL保存到文本文件里面,便于调试、修改错误。
  6. 可以方便的扩展相关功能,遵循关闭开放原则。

不承担的责任:

不对SQL语句进行检查。

不负责防止SQL注入。

不负责分页。

图示:

结构:

1、 两个工厂

CommonFactory:生成Db系列的实例,比如DbConnection、DbCommand等。内部使用。他们都是抽象基类不能直接new,需要相应的子类的实例,比如new SqlConnection、new SqlCommand等。这个就需要根据当前的需求(驱动类型)来确定了,也就是这个工厂的职责。
DALFactory:调用者使用的工厂,通过这个工厂,根据数据驱动类型,生成数据访问的实例。

2、 主体部分

DataAccessLibrary:这个是数据访问的核心部分,相当于大树的主干。定义了一个DbCommand Command,通过他来实现各种功能。

主体部分仅实现最基本的功能,定义内部结构、成员,实现输入和输出的功能。

输入主要是ExecuteNonQuery。通过他来传递添加、修改、删除的SQL语句(包括参数化SQL和存储过程)。还有一个 ExecuteExists,用来判断数据库里是否存在指定的记录。

输出部分主要是ExecuteReader,这个大家都不陌生吧。其他的原则上都是通过扩展(配件)的方式来实现,不过为了便于调用,还是增加了ExecuteString、T ExecuteScalar<T>(string text)两个函数。这个对于我来说比较常用,所以就放在主体部分里面了。

另外可以通过子类来实现支持不同数据库的差异的部分。

3、 配件部分

这个就比较多了,比如对事务的处理、对存储过程的参数的封装、对Json 的处理、对添加、修改用SQL(包括参数化SQL)的处理等。每一个都是一个“配件”,这样就可以通过增加配件的方式增加需要的功能。比如以前是不支持Json格式的记录的,但是想玩玩ajax,选择json来传递数据,那么就需要把提取出来的数据转换Json格式。那么就可以增加一个“配件”,就是增加一个类,而不影响其他代码。

增加功能,并不影响其他的代码,这个就是对扩展开放,对修改关闭。

实例

  1. //发回复    
  2. Reply.bodyUBB = Request.Form["Editor"];    
  3. Reply.topicID = int.Parse(this.DataID);    
  4. #region 验证信息    
  5. if (Reply.bodyUBB.Length < 10)    
  6. {    
  7.     Functions.PageRegisterAlert(Page, "请填写内容,或者内容太短!至少也得写10个字,对吧。");    
  8.     return;    
  9. }    
  10.  
  11. #endregion    
  12. #region 内部字段    
  13. int userID = int.Parse(UserInfo.UserID);    
  14. string ip = Request.UserHostAddress;    
  15. DateTime dateTime = DateTime.Now;    
  16. string bodyHTML;    
  17. #endregion    
  18. #region 处理UBB    
  19. bodyHTML = bodyUBB.Replace("\r", "<BR>");    
  20. //其他略    
  21. #endregion    
  22. //开启事务    
  23. Dal.ManagerTran.TranBegin();    
  24. ManagerParameter parm = Dal.ManagerParameter;    
  25. #region 设置参数    
  26. parm.ClearParameter();    
  27. parm.AddNewInParameter("TopicID", Reply.topicID);        //     
  28. parm.AddNewInParameter("回复内容", bodyUBB);    
  29. parm.AddNewInParameter("内容HTML", bodyHTML);    
  30. parm.AddNewInParameter("回复人ID", userID);    
  31. parm.AddNewInParameter("回复人IP", ip, 15);    
  32. parm.AddNewInParameter("回复时间", dateTime);    
  33. #endregion                  
  34. #region 保存回复,表名:BBS_Reply    
  35. Dal.ModifyData.InsertData("BBS_Reply");    
  36. if (Dal.ErrorMessage.Length > 0)    
  37. {    
  38.     //出现异常    
  39.     Functions.PageRegisterAlert(Page, "保存您发的回复的时候出现意外情况!");    
  40.     return;    
  41. }    
  42. #endregion    
  43. string sql;    
  44. #region 更新回复人的回复数量,回复时间,以及各种积分。    
  45. sql = @"update BBS_Topic set 回复次数 = 回复次数 + 1 ,***回复时间 = GetDate(),    
  46. ***回复人ID = {0},   where TopicID ={1}";    
  47. Dal.ExecuteNonQuery(string.Format(sql, userID,topicID));    
  48. if (Dal.ErrorMessage.Length > 0)    
  49. {    
  50.     //出现异常    
  51.     Functions.PageRegisterAlert(Page, "更新回复数量的时候出现意外情况!");    
  52.     return;    
  53. }    
  54. #endregion    
  55. #region 更新回复人的参与讨论的帖子    
  56. sql = "select top 1 UserInTopicID from BBS_UserInTopic where UserID ={0} and TopicID={1} ";    
  57. string userInTopicID = Dal.ExecuteString(string.Format(sql, userID, topicID));    
  58. sql = "select top 1 回复次数 from BBS_Topic where TopicID={0} ";    
  59. string reCount = Dal.ExecuteString(string.Format(sql, topicID)) ?? "0";    
  60. int intintReCount = int.Parse(reCount);    
  61. if (userInTopicID == null)    
  62. {    
  63.     #region 没有参与过,添加记录    
  64.     parm.ClearParameter();    
  65.     parm.AddNewInParameter("UserID", userID);    
  66.     parm.AddNewInParameter("TopicID", topicID);    
  67.     parm.AddNewInParameter("***查看时间", dateTime);    
  68.     parm.AddNewInParameter("***查看回复数", intReCount);    
  69.     Dal.ModifyData.InsertData("BBS_UserInTopic");    
  70.     if (Dal.ErrorMessage.Length > 0)    
  71.     {    
  72.         //出现异常    
  73.         Functions.PageRegisterAlert(Page, "增加您参与讨论的帖子的时候出现意外情况!");    
  74.         return;    
  75.     }    
  76.     #endregion    
  77. }    
  78. else   
  79.  
  80. {    
  81.     #region 参与过,修改记录    
  82.     parm.ClearParameter();    
  83.     parm.AddNewInParameter("***查看时间", dateTime);    
  84.     parm.AddNewInParameter("***查看回复数", intReCount);    
  85.     Dal.ModifyData.UpdateData("BBS_UserInTopic", "UserInTopicID=" + userInTopicID);    
  86.     if (Dal.ErrorMessage.Length > 0)    
  87.     {    
  88.         //出现异常    
  89.         Functions.PageRegisterAlert(Page, "更新参与讨论的帖子的时候出现意外情况!");    
  90.         return;    
  91.     }    
  92.     #endregion    
  93. }    
  94. #endregion    
  95. //提交事务    
  96. Dal.ManagerTran.TranCommit();    
  97. //正常    
  98. lblMsg.Text = "发表回复成功!感谢您的参与!1秒后重新加载帖子。";    
  99. Functions.PageRegisterJavascript(Page, "reload()");    

简单写一个,以论坛的回复为例,这个大家都熟悉,不是太简单也不是很复杂。

这个没有按照三层的方式来写,因为我分不出来哪些是业务逻辑,哪些是数据访问,都写到一起了,呵呵。但是这并不是说数据访问只能写成这个样子。这个只是一个具体的、综合性的例子。也可以把他分一分,找到业务逻辑的部分,提取出去,放在业务层;把数据访问的部分也提出出去,放在数据层。

这里仅仅是一个数据访问的调用的示例,并不是说要不要分层。

原文出处:http://www.cnblogs.com/jyk/archive/2011/03/28/1998254.html

【编辑推荐】

  1. 晒晒我的通用数据访问层
  2. 几步走,教你创建简单访问数据库方法
  3. 一句代码实现批量数据绑定 下
  4. 一步一步设计你的数据库1
  5. 不重复随机数列生成算法
责任编辑:艾婧 来源: 博客园
相关推荐

2011-04-22 10:50:18

SimpleFrame

2011-03-03 11:07:57

Spring数据库访问ORM

2018-07-13 09:20:30

SQLite数据库存储

2011-11-14 10:41:15

Winform数据管理模块Items

2019-04-08 17:11:46

大数据框架Spark

2017-04-28 08:13:08

大数据框架HDFS

2021-12-30 08:17:27

Springboot数据访问DataSourceB

2021-05-18 07:15:37

Python

2021-09-15 08:09:43

前端技术编程

2021-09-03 12:01:07

模型自然语言

2019-06-13 11:50:41

Python面向对象编程语言

2009-10-29 17:33:51

VB.NET线程方法

2011-11-02 09:01:30

系统架构师

2009-07-29 17:38:15

数据中心冷却服务器

2012-08-15 11:03:18

框架项目

2022-06-07 07:58:45

SpringSpring AOP

2022-05-27 08:25:55

容器Spring

2016-03-23 11:05:58

Socket开发框架分析

2021-07-09 13:54:31

零信任网络安全网络攻击

2011-06-20 10:19:27

点赞
收藏

51CTO技术栈公众号