数据访问层的使用方法

数据访问层的使用方法。

数据访问层的使用方法

一、操作语句部分

简单的说就是传入一个操作语句,然后接收返回值就可以了。为了简化代码和提高效率,所以呢设置了五种返回类型。

1、 DataSet

函数名称:DateSet ds = RunSqlDataSet(查询语句)

传入一个查询语句(多条select 的查询语句),然后接收返回值就可以了。

没有记录返回 null

2、 DataTable

函数名称:DateTable dt = RunSqlDataTable(查询语句)

传入一个查询语句(一条select 的查询语句),然后接收返回值就可以了。

没有记录返回 null

3、 DataRow

函数名称:DataRow dr = RunSqlDataRow(查询语句)

传入一个查询语句(一条select 的查询语句),然后接收返回值就可以了。

没有记录返回 null

4、 String[]

函数名称:string[] str = RunSqlStrings (查询语句)

传入一个查询语句(一条select 的查询语句),然后接收返回值就可以了。

没有记录返回 null

5、 String

函数名称:string str = RunSqlGetID (查询语句)

传入一个查询语句(一条select 的查询语句),然后接收返回值就可以了。

没有记录返回 null

6、 Null

函数名称:RunSql (操作语句)

传入一个操作语句(insert 、update、delete的操作语句)。

说明:参数都是字符串型的。

二、存储过程部分

简单的说就是和查询语句的很类似了,只不过多了个存储过程的参数。

1、 DataSet

函数名称:DateSet ds = RunStoreDataSet(存储过程的名称)

传入存储过程的名称,然后接收返回值。

没有记录返回 null

2、 DataTable

函数名称:DateTable dt = RunStoreDataTable(存储过程的名称)

传入存储过程的名称,然后接收返回值。

没有记录返回 null

3、 Null

函数名称:RunStore (存储过程的名称)

传入存储过程的名称。

三、存储过程的参数(1)

如果没有参数的话,那么存储过程的用法和查询语句的也就一样了。但是呢,大多数的存储过程都是有参数的,不过有了参数我们也不怕!

我们可以用addNewParameter方法来添加存储过程的参数。不用像SQLHelp那样麻烦,还得传入一个Parameter的对象。我们直接调用数据访问层的方法就可以了。

这里通过函数重载的方式来区分不同的数据类型。以C#里的数据类型为标准,对应SQL里面的数据类型。

1、 int型的参数

这里对应三个SQL Server的数据类型:int、tinyint、smallint

函数名称:addNewParameter(string ParameterName,int ParameterValue)

ParameterName:参数名称。

ParameterValue:参数值。

2、 bit型的参数

这里对应一个SQL Server的数据类型:bit

函数名称:addNewParameter(string ParameterName,bool ParameterValue)

ParameterName:参数名称。

ParameterValue:参数值。

3、 double型的参数

这里对应两个SQL Server的数据类型:float、real

函数名称:addNewParameter(string ParameterName,double ParameterValue )

ParameterName:参数名称。

ParameterValue:参数值。

4、 string型的参数

这里对应七个SQL Server的数据类型:char、nchar、varchar、nvarchar、uniqueidentifier、smalldatetime、datetime

函数名称:addNewParameter(string ParameterName,string ParameterValue,int size)

ParameterName:参数名称。

ParameterValue:参数值。

Size: 参数的大小。

5、 ntext型的参数

这里对应两个SQL Server的数据类型:ntext、text

函数名称:addNewParameter(string ParameterName,string ParameterValue)

ParameterName:参数名称。

ParameterValue:参数值。

6、 金额型的参数

这里对应三个SQL Server的数据类型:decimal、smallmoney、money

函数名称:addNewParameter(string ParameterName,decimal ParameterValue)

ParameterName:参数名称。

ParameterValue:参数值。

7、 说明

还有二进制类型的没有处理。忘记要用C#的哪个类型来对应了。

这里添加的参数都是输入型(input)的,如果想设置输出型的参数请看下面。

四、存储过程的参数(2)

这里讲述如何设置输出型(output)的参数,以及如何修改参数值、取值和清除参数

1、 设置输出型参数

函数名称:addNewParameter(string ParameterName,ZDIC.ParameterKind kind)

ParameterName:参数名称。

Kind:参数类型。

2、 获取参数的返回值

函数1名称:getParameter(int ParameterIndex)

ParameterIndex:参数的序号。

通过参数的序号来返回参数值。

函数2名称:getParameter(string ParameterName)

ParameterName:参数的名称。

通过参数名称来返回参数值。

3、 修改参数值

函数1名称:setParameter(int ParameterIndex,string parameterValue)

ParameterIndex:参数的序号。

通过参数的序号来修改参数值。

函数2名称:setParameter(string ParameterName,string parameterValue)

ParameterName:参数的名称。

通过参数名称来修改参数值。

4、 清除参数

函数名称:ClearParameter()

执行一下就行除了。

五、异常处理

这里并不向上层抛出异常,取代的是给ErrorMsg属性赋值。如果程序正常执行,则ErrorMsg==”0”表示没有发生异常;否则ErrorMsg的内容就是错误描述。

错误描述包括三个部分:函数名称,执行的查询语句(存储过程)和系统给出的错误信息。这样呢就很容易发现出错的地方,尤其是在使用查询语句的时候。

六、错误日志

在发生异常的时候,会自动记录错误信息,以便日后的维护和修改错误。

错误日志以文本文件的形式存放在 /log文件夹下面,文件名是yyyyMMdd的格式。

为什么用文本文件而不用数据库?因为一般在正式使用后发生的异常大多都是由于数据库造成的,所以很有可能在发生异常之后已经无法再向数据库里写信息了。而向文本文件里写信息一般是不会出错的。

七、连接字符串及Connection对象

连接字符串是从 Connection.dll 里面读取的,其目的是适应连接字符串的各种变化。比如是否加密,用什么算法加密;连接字符串存放在什么地方?web.config、DLL、注册表或者其他的什么地方。引用Conection.dll后就可以很轻松的应对以上的这些要求。

八、事务处理

利用 Connection.BeginTransaction 等方法实现事务。没有作严格的测试,因为目前还没有用到。

九、更换数据库

这里是针对SQL Server 数据库做的处理,也就是对SqlClinet进行的封装。如果更换数据库的话,那么只需要把Sql字样换成对应的数据库的表示就可以了。其他的作一些适当的调整就可以了。

十、使用示例

以新闻系统为例

1、 用查询语句的方式获取新闻列表,然后绑定Repeater控件。

DataAccessLayer dal = new DataAccessLayer();

Rpt.DataSource = dal.RunSqlDataTable("select NewsID,addedDate,title from news ");

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

Rpt.DataBind();

2、 用存储过程的方式获取新闻列表,然后绑定Repeater控件。

DataAccessLayer dal = new DataAccessLayer();

Rpt.DataSource = dal.RunStoreDataTable("Proc_News_list");

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

Rpt.DataBind();

3、 用string[]的方式获取一条新闻纪录。然后给Label控件赋值。

DataAccessLayer dal = new DataAccessLayer();

string sql = "select Title,AddedDate,Content from News where NewsID=" + NewsID

string[] Infos = dal.RunSqlStrings(sql);

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

if (Infos == null)

{

Response.Write("没有这条新闻!");

Response.End();

}

Lbl_Title.Text = Infos[0];

Lbl_AddedDate.Text = Infos[1].Split(' ')[0];

Lbl_Content.Text = Infos[2];

4、 用DataRow的方式获取一条新闻纪录。然后给Label控件赋值。

DataAccessLayer dal = new DataAccessLayer();

string sql = "select Title,AddedDate,Content from News where NewsID=" + NewsID

DataRow Infos = dal.RunSqlDataRow(sql);

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

if (Infos == null)

{

Response.Write("没有这条新闻!");

Response.End();

}

Lbl_Title.Text = Infos["Title"].ToString();

Lbl_AddedDate.Text = Infos["AddedDate"] .ToString().Split(' ')[0];

Lbl_Content.Text = Infos["Content"] .ToString();

5、 用InsertDataStr和UpdateData实现添加、修改新闻。同时用RunSqlExists判断新闻标题是否重复。

//判断是修改还是添加

bool isAdd = false;

if (DG.SelectedIndex == -1) //利用DataGrid的状态来判断是添加还是修改。

isAdd = true;

//设定字段。这里一定要用一个数组来表示,这是 InsertDataStr 函数的参数的要求!

string[] str1 = new string[2];

str1[0] = "title";

str1[1] = "Content";

//获取用户输入的信息,并且过滤危险字符

//这里一定要用一个数组来表示,这是 InsertDataStr 函数的参数的要求!

string[] str = new string[2];

str[0] = this.Txt_Title.Text.Trim().Replace("'","");

str[1] = this.Txt_Content.Text.Trim().Replace("'","");

#region 数据验证

if (str[0].Length == 0 )

{

Page.RegisterStartupScript("a",Functions.myAlert("请填写新闻标题!"));

return;

}

DataAccessLayer dal = new DataAccessLayer();

if (isAdd)

{

if (dal.RunSqlExists("select top 1 '1' from news where title='" + str[0] + "'" ))

{

Page.RegisterStartupScript("a",Functions.myAlert("已经有这个新闻标题了!"));

return;

}

}

else

{

if (dal.RunSqlExists("select top 1 '1' from news where title='" + str[0] + "' and NewsID <>" + DG.SelectedItem.Cells[0].Text))

{

Page.RegisterStartupScript("a",Functions.myAlert("已经有这个新闻标题了!"));

return;

}

}

#endregion

if (isAdd)

//添加新闻

dal.InsertDataStr("News",str1,str);

else

//修改新闻

dal.UpdateData("News",str1,str," NewsID=" + DG.SelectedItem.Cells[0].Text);

//检查是否出现异常

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

if (isAdd)

//添加成功。进行相应处理

else

//修改成功。进行相应处理

6、 用RunStore 用的方式添加修改新闻

//判断是修改还是添加

bool isAdd = false;

if (DG.SelectedIndex == -1) //利用DataGrid的状态来判断是添加还是修改。

isAdd = true;

//获取用户输入的信息,存储过程的方式就不用过滤了

string NewsTitle = this.Txt_Title.Text.Trim();

string NewsContent = this.Txt_Content.Text;

// 数据验证

if (str[0].Length == 0 )

{

Page.RegisterStartupScript("a",Functions.myAlert("请填写新闻标题!"));

return;

}

//标题是否重复的判断由存储过程来实现

DataAccessLayer dal = new DataAccessLayer();

//添加存储过程的参数

dal.addNewParameter("@title",NewsTitle,100);

dal.addNewParameter("@Content",NewsContent);

//output型的参数

dal.addNewParameter("@ReturnMsg",ParameterKind.NVarChar );

if (!isAdd)

//修改新闻,需要给 @NewsID 负值。

dal.addNewParameter("@NewsID",Int32.Parse(DG.SelectedItem.Cells[0].Text))

//执行存储过程

dal.RunStore("Proc_News_ModData");

//检查是否出现异常

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

string err = dal.getParameter("@ReturnMsg");//获取参数的返回值

if (isAdd)

{//添加状态

if (err.Length > 1)

{

//显示存储过程里面返回的错误信息,比如新闻标题重名等。

}

else

{

//添加成功

SetFormEmpty();

}

}

else

{//修改状态

if (err.Length > 1)

{

//显示存储过程里面返回的错误信息,比如新闻标题重名等。

}

else

{

//修改成功

SetFormVisible(false);

}

}

7、 用RunSql 删除新闻

DataAccessLayer dal = new DataAccessLayer();

dal.RunSql("delete from News where NewsID=" + e.Item.Cells[0].Text);

//检查是否出现异常

if (dal.ErrorMsg.Length > 2 )

{

Response.Write(dal.ErrorMsg ); //输出错误信息

return;

}

8、 说明

除了添加修改的地方,代码都是非常简洁的。可以说只用了一行就达到了目的。由于省去了实体层,数据访问层也变成了DLL类库,所以说呢,从表面上看程序的结构就变成了一层结构了,也就是说只需写这些代码就可以实现一个模块的基本功能了。

再来看看添加修改的地方。虽然代码好像多了一点,但是合并了添加、修改的共同的地方,减少了三分之一的代码。可能会比三层结构的UI层的代码量多一些,但是没有实体层、业务逻辑层和数据访问层的代码。重整体上来说减少了三倍的代码量。

修改上也是很方便的。如果要修改字段名称的话,只需要修改str1数组里对应的值就可以了;添加字段呢,只需要增加str1和str数组的大小,并负值就可以了。省去了其他层的修改(因为根本就没有在其他的地方写代码!)

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏pangguoming

Python相对、绝对导入浅析

这篇文章从另外一个不同的视角来分析一下Python的import机制,主要的目的是为了搞懂import中absolute、relative import遇到的几...

43370
来自专栏开发技术

spring-boot-2.0.3不一样系列之源码篇 - SpringApplication的run方法(一)之SpringApplicationRunListener,绝对有值得你看的地方

  Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,...

19620
来自专栏FreeBuf

Nebula漏洞利用包CVE-2016-0189漏洞利用分析

1. 引言 在最近的一年里, 漏洞利用工具包(EK/Exploit Kit)市场风云变幻。2016年六月初,曾经极为猖獗的Angler EK 销声匿迹,Neut...

28560
来自专栏小樱的经验随笔

新人入坑Redis必会的吐血总结

Redis是一个使用C语言开发的开源的高性能的key-value存储系统,我们可以把它近似理解为Java Map。简单来讲,Redis是一种NOSQL内存数据库...

1.7K20
来自专栏Java帮帮-微信公众号-技术文章全总结

JavaWeb10-request&response你不得不学(1)

? request&response 一.request和response的介绍 1. request和response的作用执行流程 Web服务器收到客户端...

81340
来自专栏高爽的专栏

Java线程(九):Condition-线程通信更高效的方式

        接近一周没更新《Java线程》专栏了,主要是这周工作上比较忙,生活上也比较忙,呵呵,进入正题,上一篇讲述了并发包下的Lock,Lock可以更好的...

28800
来自专栏圣杰的专栏

Ajax.BeginForm()知多少

在ASP.NET MVC中,Ajax.BeginForm扮演着异步提交的重要角色。其中就有五个重载方法,但是在实际应用中,你未必使用的得心应手,今天我们就从主要...

27260
来自专栏Java技术分享

《Redis设计与实现》简读

最佳实践:因为对字符串的增长或缩短操作都有可能需要执行内存重分配,所以修改相同键使用SDS类型保存的值时保持修改前后长度一致。

20280
来自专栏Golang语言社区

设计包导出接口的随想

简介:本文讨论在设计一个包的导出接口时遇到的问题以及所采取的解决思路和方法,并提供了模拟代码作为例子。 假设有一个包gameword有个导出结构Player,包...

34860
来自专栏Python攻城狮

Python进程VS线程1.进程和线程2.同步的概念3.互斥锁4.多线程-非共享数据5.同步应用6.生产者与消费者模式

队列: 1、进程之间的通信: q = multiprocessing.Queue() 2、进程池之间的通信: q = multiproc...

12130

扫码关注云+社区

领取腾讯云代金券