【自然框架】之数据访问 —— 再小的类库也需要设计。

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

目标:

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

特点:

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

不承担的责任: 1、 不对SQL语句进行检查。 2、 不负责防止SQL注入。 3、 不负责分页。

图示:

结构:

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格式。那么就可以增加一个“配件”,就是增加一个类,而不影响其他代码。   增加功能,并不影响其他的代码,这个就是对扩展开放,对修改关闭。

实例

//发回复  

Reply.bodyUBB = Request.Form["Editor"];  

Reply.topicID = int.Parse(this.DataID);  

#region 验证信息  

if (Reply.bodyUBB.Length < 10)  

{  

    Functions.PageRegisterAlert(Page, "请填写内容,或者内容太短!至少也得写10个字,对吧。");  

 return;  

}  

#endregion 

#region 内部字段  

int userID = int.Parse(UserInfo.UserID);  

string ip = Request.UserHostAddress;  

DateTime dateTime = DateTime.Now;  

string bodyHTML;  

#endregion 

#region 处理UBB  

bodyHTML = bodyUBB.Replace("\r", "<BR>");  

//其他略  

#endregion 

//开启事务  

Dal.ManagerTran.TranBegin();  

ManagerParameter parm = Dal.ManagerParameter;  

#region 设置参数  

parm.ClearParameter();  

parm.AddNewInParameter("TopicID", Reply.topicID);        // 

parm.AddNewInParameter("回复内容", bodyUBB);  

parm.AddNewInParameter("内容HTML", bodyHTML);  

parm.AddNewInParameter("回复人ID", userID);  

parm.AddNewInParameter("回复人IP", ip, 15);  

parm.AddNewInParameter("回复时间", dateTime);  

#endregion 

 

#region 保存回复,表名:BBS_Reply  

Dal.ModifyData.InsertData("BBS_Reply");  

if (Dal.ErrorMessage.Length > 0)  

{  

 //出现异常  

    Functions.PageRegisterAlert(Page, "保存您发的回复的时候出现意外情况!");  

 return;  

}  

#endregion 

string sql;  

#region 更新回复人的回复数量,回复时间,以及各种积分。  

sql = @"update BBS_Topic set 回复次数 = 回复次数 + 1 ,最后回复时间 = GetDate(),  

最后回复人ID = {0},   where TopicID ={1}";  

Dal.ExecuteNonQuery(string.Format(sql, userID,topicID));  

if (Dal.ErrorMessage.Length > 0)  

{  

 //出现异常  

    Functions.PageRegisterAlert(Page, "更新回复数量的时候出现意外情况!");  

 return;  

}  

#endregion 

#region 更新回复人的参与讨论的帖子  

sql = "select top 1 UserInTopicID from BBS_UserInTopic where UserID ={0} and TopicID={1} ";  

string userInTopicID = Dal.ExecuteString(string.Format(sql, userID, topicID));  

sql = "select top 1 回复次数 from BBS_Topic where TopicID={0} ";  

string reCount = Dal.ExecuteString(string.Format(sql, topicID)) ?? "0";  

int intReCount = int.Parse(reCount);  

if (userInTopicID == null)  

{  

 #region 没有参与过,添加记录  

    parm.ClearParameter();  

    parm.AddNewInParameter("UserID", userID);  

    parm.AddNewInParameter("TopicID", topicID);  

    parm.AddNewInParameter("最后查看时间", dateTime);  

    parm.AddNewInParameter("最后查看回复数", intReCount);  

    Dal.ModifyData.InsertData("BBS_UserInTopic");  

 if (Dal.ErrorMessage.Length > 0)  

    {  

 //出现异常  

        Functions.PageRegisterAlert(Page, "增加您参与讨论的帖子的时候出现意外情况!");  

 return;  

    }  

 #endregion 

}  

else 

{  

 #region 参与过,修改记录  

    parm.ClearParameter();  

    parm.AddNewInParameter("最后查看时间", dateTime);  

    parm.AddNewInParameter("最后查看回复数", intReCount);  

    Dal.ModifyData.UpdateData("BBS_UserInTopic", "UserInTopicID=" + userInTopicID);  

 if (Dal.ErrorMessage.Length > 0)  

    {  

 //出现异常  

        Functions.PageRegisterAlert(Page, "更新参与讨论的帖子的时候出现意外情况!");  

 return;  

    }  

 #endregion 

}  

#endregion 

//提交事务  

Dal.ManagerTran.TranCommit();  

//正常  

lblMsg.Text = "发表回复成功!感谢您的参与!1秒后重新加载帖子。";  

Functions.PageRegisterJavascript(Page, "reload()"); 
 

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我是攻城师

图形数据库之Neo4j学习(一)

3885
来自专栏hbbliyong

JAVA试练塔之试炼技能图

1.计算机基础: 1.1数据机构基础: 主要学习: 1.向量,链表,栈,队列和堆,词典。熟悉 2.树,二叉搜索树。熟悉 3.图,有向图,无向图,基本概念 4.二...

3807
来自专栏Hongten

python开发_常用的python模块及安装方法

adodb:我们领导推荐的数据库连接组件 bsddb3:BerkeleyDB的连接组件 Cheetah-1.0:我比较喜欢这个版本的cheetah cherry...

3533
来自专栏杨建荣的学习笔记

system表空间不足的问题分析(r6笔记第66天)

很多事情见多了也就有了麻木的感觉,报警短信就是如此,每天总能收到不少的报警短信,可能很多时候就扫一眼,如果没有严重的问题自己是不会情愿打开电脑处理的。 对于此,...

2744
来自专栏有趣的django

Django+xadmin打造在线教育平台(九)

代码 github下载 十二、首页和全局404,500配置 12.1.首页功能 Course添加一个字段 is_banner = models.Boolean...

5926
来自专栏跟着阿笨一起玩NET

asp.net采用OLEDB方式导入Excel数据时提示:未在本地计算机上注册"Microsoft.Jet.OLEDB.4.0" 提供程序"

 笔者在项目中做做了一个从Excel表格中导入数据的模块、大体上asp.net项目中导入Excel大体分成三类:

6091
来自专栏安富莱嵌入式技术分享

【二代示波器教程】第14章 uCOS-III操作系统版本二代示波器实现

本章教程为大家讲解uCOS-III操作系统版本的二代示波器实现。主要讲解RTOS设计框架,即各个任务实现的功能,任务间的通信方案选择,任务栈,系统栈以及全局变量...

1555
来自专栏黑泽君的专栏

从零讲JAVA ,给你一条清晰地学习道路!该学什么就学什么!!

 原文链接:https://zhuanlan.zhihu.com/p/25296859

992
来自专栏大数据挖掘DT机器学习

Python实现爬取知乎神回复

这篇文章主要介绍了Python实现爬取知乎神回复简单爬虫代码分享,本文实现了爬取知乎的“如何正确地吐槽”收藏夹,是对个人的一个兴趣实现,需要的朋友可以参考下。 ...

3425
来自专栏恰同学骚年

ASP.Net WebForm温故知新学习笔记:二、ViewState与UpdatePanel探秘

开篇:经历了上一篇《aspx与服务器控件探秘》后,我们了解了aspx和服务器控件背后的故事。这篇我们开始走进WebForm状态保持的一大法宝—ViewState...

1593

扫码关注云+社区

领取腾讯云代金券