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

简介:   以前也写过几篇关于数据访问的,这里是最新的总结。麻雀虽小五脏俱全,数据访问也许不起眼,但是也要好好的设计一翻。从2004年开始用自己的数据访问,一直到现在,经历过两次大的改版,随着需求的变化,也增加了不少的功能,小修小改那就更多了。

 

  以前也写过几篇关于数据访问的,这里是最新的总结。麻雀虽小五脏俱全,数据访问也许不起眼,但是也要好好的设计一翻。从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() " ); 

 


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

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

相关文章
|
8月前
|
安全 Java 数据安全/隐私保护
|
5月前
|
安全 前端开发 Java
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择。依赖注入使对象管理交由Spring容器处理,实现低耦合高内聚;AOP则分离横切关注点如事务管理,增强代码模块化。Spring还提供MVC、Data、Security等模块满足多样需求,并通过Spring Boot简化配置与部署,加速微服务架构构建。掌握这些核心概念与工具,开发者能更从容应对挑战,打造卓越应用。
49 1
|
4月前
|
Java 数据处理
技术分享:高效与灵活并存——Java版通用树形结构转换工具的实现与应用
在软件开发中,树形结构的数据表现形式无处不在,从文件系统的目录树到组织架构的部门树,再到各类产品的分类结构。处理这些具有层级关系的数据时,将其转换为树形结构以便展示和操作显得尤为重要。Java作为一门成熟的编程语言,虽然提供了强大的集合框架,但并未直接提供树形结构转换的内置工具。因此,开发一个高效且灵活的通用树形结构转换工具成为许多项目中的必备需求。
108 2
|
4月前
|
存储 NoSQL 数据处理
组合和继承怎么集成一个性能较好的项目
组合与继承是面向对象编程的核心概念,前者通过对象间关联实现高效解耦,后者则重用代码以节省空间和内存。组合常用于现代项目,利用代理与依赖注入简化代码管理;而继承简化了子模块对父模块资源的应用,但修改会影响整体。随着分层解耦及微服务架构如SpringCloud的出现,这些技术进一步优化了数据处理效率和服务响应性能,尤其在分布式存储与高并发场景下。同步异步调用、Redis分布式应用等也广泛运用组合与继承,实现代码和内存空间的有效复用。
|
8月前
|
SQL Java 数据库连接
深度解析MyBatis核心:探寻其核心对象的精妙设计
深度解析MyBatis核心:探寻其核心对象的精妙设计
116 1
深度解析MyBatis核心:探寻其核心对象的精妙设计
|
8月前
|
算法 测试技术 数据处理
【C++ 设计思路】优化C++项目:高效解耦库接口的实战指南
【C++ 设计思路】优化C++项目:高效解耦库接口的实战指南
207 5
|
8月前
|
存储 Java
java反射——设计框架的灵魂
java反射——设计框架的灵魂
|
小程序 前端开发 API
阿里云小程序框架优点
阿里云小程序框架优点
|
设计模式 开发框架 前端开发
设计概念的统一语言
设计概念的统一语言
|
存储 网络协议 安全
WEB服务端开发必懂的概念和底层原理,通过对比的方式让大家更好的理解和使用
golang 源码级别支持协程,实现简单。协程使用,当底层遇到阻塞会自动切换,也就是逻辑层通过同步方式实现异步,充分利用了系统资源,同时避免了异步状态机的反人类异步回调,实现方式更为直观简单。golang 协程是通过多线程维护,所以避免不了锁的使用,但也极大解决了研发效率问题。
204 0