代码改变世界

数据访问层的使用方法

2006-08-16 04:54  金色海洋(jyk)  阅读(1955)  评论(1编辑  收藏  举报
数据访问层的使用方法。

数据访问层的使用方法

 

一、操作语句部分

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

 

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、  InsertDataStrUpdateData实现添加、修改新闻。同时用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数组的大小,并负值就可以了。省去了其他层的修改(因为根本就没有在其他的地方写代码!)

2