分页解决方案 之 数据访问函数库——另类的思路、另类的写法,造就了不一样的发展道路。

简介:     上一篇:分页解决方案 —— GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + 数据库         如何访问数据库?一个老掉牙的问题,方法多了去了,什么直接使用ado.net、使用SQLHelp、使用微软的企业库、使用ORM、使用LinQ to SQL等等,还可以使用自己封装的函数库,这里我就想说一下我的数据访问函数库的使用方法。

 

    上一篇:分页解决方案 —— GridView + QuickPager + QuickPager_SQL + DataAccessLibrary + 数据库  

 

    如何访问数据库?一个老掉牙的问题,方法多了去了,什么直接使用ado.net、使用SQLHelp、使用微软的企业库、使用ORM、使用LinQ to SQL等等,还可以使用自己封装的函数库,这里我就想说一下我的数据访问函数库的使用方法。

 

    您可能会说了,这么简单的东东还用说吗,重复制作轮子有意义吗?这个嘛,个人有个人的看法了,我也不多说了,先看使用方法吧。

 

     忘记说了,我的数据访问函数库不是静态的,所以需要先实例化。

DataAccessLibrary dal = DALFactory.CreateDAL();

1、删除一条数据,不使用事务

 

protected   void  Btn_Del_Click( object  sender, EventArgs e)
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif        
{
            
//不用事务,直接删除数据
            string sql = "delete from News_NewsInfo where newsID = 18 ";
            
            
//执行SQL语句
            dal.ExecuteNonQuery(sql);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的删除了一条数据#region 判断是否出现异常 和 是否真的删除了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                Functions.PageRegisterAlert(Page,"删除数据的时候发生异常,请与管理员联系!");
                
return;
            }

            
//判断是否真的删除了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确删除一条数据,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "没有正确删除这条数据,请与管理员联系!");
                
return;
            }

            
#endregion


        }

 

2、删除多条数据,使用事务

 

protected   void  Btn_DelMore_Click( object  sender, EventArgs e)
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif        
{
            
//使用事务,删除多个表里面的数据

            
//开启一个事务
            dal.TranManager.TranBegin();
 
            
string sql = "delete from News_NewsInfo where newsID = 13 ";

            
//执行SQL语句
            dal.ExecuteNonQuery(sql);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的删除了一条数据#region 判断是否出现异常 和 是否真的删除了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                
//数据访问函数库内部会自动回滚事务,外部不用回滚!
                Functions.PageRegisterAlert(Page, "删除数据的时候发生异常,请与管理员联系!");
                
return;
            }

            
            
//判断是否真的删除了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确删除一条数据,客户端弹出提示信息
                
//没有产生异常,内部并没有自动回滚事务,所以请调用回滚的函数,回滚事务!
                dal.TranManager.TranRollBack();
                Functions.PageRegisterAlert(Page, 
"没有正确删除这条数据,请与管理员联系!");
                
return;
            }

            
#endregion


            sql 
= "delete from News_NewsInfo where newsID = 14  ";
            
//执行SQL语句
            dal.ExecuteNonQuery(sql);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的删除了一条数据#region 判断是否出现异常 和 是否真的删除了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                
//数据访问函数库内部会自动回滚事务,外部不用回滚!
                Functions.PageRegisterAlert(Page, "删除数据的时候发生异常,请与管理员联系!");
                
return;
            }


            
//判断是否真的删除了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确删除一条数据,客户端弹出提示信息
                
//没有产生异常,内部并没有自动回滚事务,所以请调用回滚的函数,回滚事务!
                dal.TranManager.TranRollBack();
                Functions.PageRegisterAlert(Page, 
"没有正确删除这条数据,请与管理员联系!");
                
return;
            }

            
#endregion


            
//可以继续执行其他的操作,不仅仅是删除语句,insert、Update语句都可以执行。
            
//执行之后都要进行判断

            
//所有的操作都正确执行完毕之后,需要提交事务
            dal.TranManager.TranCommit();

            
//注意,事务不支持嵌套!

            
        }

 

3、使用参数化SQL语句添加数据

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 参数化SQL语句的方式添加数据 #region 参数化SQL语句的方式添加数据
            
//清除参数
            dal.ParameterManager.ClearParameter();
            
//添加参数
            dal.ParameterManager.AddNewInParameter("@Title""参数化SQL语句的标题"50);    //nvarchar类型的参数,需要指定长度
            dal.ParameterManager.AddNewInParameter("@Content""嘻嘻哈哈");                 //ntext 类型的不需要指定长度
            dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now);           //日期型的
            dal.ParameterManager.AddNewInParameter("@Hits"3);                             //int型的

            
//执行参数化的SQL语句,返回新添加的数据的ID值,只限于自增字段的表。
            string newID = dal.InsertData("News_NewsInfo"); 

            Response.Write(newID);
            Response.Write(
"<BR>" + dal.ExecuteRowCount);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的删除了一条数据#region 判断是否出现异常 和 是否真的删除了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "添加数据的时候发生异常,请与管理员联系!");
                
return;
            }


            
//判断是否真的添加了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            
//由于最后使用了select scope_identity() as a1 来得到新增记录的主键值,所以ExecuteRowCount值为零。
            
//我还不知道没能正确添加数据的话 scope_identity()会返回什么?所以这里就不知道要怎么判断了,呵呵
            
//if (newID != 0)
            
//{
            
//    //没有正确删除一条数据,客户端弹出提示信息
            
//    Functions.PageRegisterAlert(Page, "没有正确添加这条数据,请与管理员联系!");
            
//    return;
            
//}
            #endregion


            
#endregion

 

4、使用储存过程添加数据

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif              存储过程的方式添加数据 #region 存储过程的方式添加数据
            
//和参数化的SQL语句基本相同,不同点有两个地方,一个是要事先建立存储过程,一是使用ExecuteNonQuery。

            
//清除参数
            dal.ParameterManager.ClearParameter();
            
//添加参数
            dal.ParameterManager.AddNewInParameter("@Title""储存过程的标题"50);    //nvarchar类型的参数,需要指定长度
            dal.ParameterManager.AddNewInParameter("@Content""嘻嘻哈哈");                 //ntext 类型的不需要指定长度
            dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now);           //日期型的
            dal.ParameterManager.AddNewInParameter("@Hits"3);                             //int型的

            
//添加返回型的参数
            dal.ParameterManager.AddNewOutParameter("@NewsID",DbType.Int32 );

            
//存储过程的名称要以Proc开头
            
//如果您不习惯Proc开头的话,那么需要修改数据访问函数库的内部函数。
            
//不建议使用xp_、sp_等开头,因为系统的存储过程的名称是以这些开头的。

            
//执行储存过程
            dal.ExecuteNonQuery("Proc_News_Mod");

            
//获取储存过程的参数
            newID = dal.ParameterManager["@NewsID"].Value.ToString();

            Response.Write(
"<BR>" + newID);
            Response.Write(
"<BR>" + dal.ExecuteRowCount);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的添加了一条数据#region 判断是否出现异常 和 是否真的添加了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "添加数据的时候发生异常,请与管理员联系!");
                
return;
            }


            
//判断是否真的添加了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确添加一条数据,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "没有正确添加这条数据,请与管理员联系!");
                
return;
            }

            
#endregion

            
#endregion

 

5、使用参数化SQL语句修改数据

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif              参数化SQL语句的方式修改数据 #region 参数化SQL语句的方式修改数据
            
//添加参数
            dal.ParameterManager.ClearParameter();
            dal.ParameterManager.AddNewInParameter(
"@Title""参数化SQL语句的标题"50);    //nvarchar类型的参数,需要指定长度
            dal.ParameterManager.AddNewInParameter("@Content""嘻嘻哈哈");                 //ntext 类型的不需要指定长度
            dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now);             //日期型的
            dal.ParameterManager.AddNewInParameter("@Hits"3);                             //int型的

            
//修改存储过程的参数的值
            dal.ParameterManager["@Title"].Value  = "后来修改了";

            
//执行参数化的SQL语句,设置条件已修改数据。
            dal.UpdateData ("News_NewsInfo","NewsID = 21");

            Response.Write(
"<BR>" + dal.ExecuteRowCount);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的修改了一条数据#region 判断是否出现异常 和 是否真的修改了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "修改数据的时候发生异常,请与管理员联系!");
                
return;
            }


            
//判断是否真的修改了一条数据
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确删除一条数据,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "没有正确修改这条数据,请与管理员联系!");
                
return;
            }

            
#endregion


            
#endregion

 

6、使用储存过程修改数据

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif             存储过程的方式修改数据 #region 存储过程的方式修改数据
            
//和参数化的SQL语句基本相同,不同点有两个地方,一个是要事先建立存储过程,一是使用ExecuteNonQuery。

            
//清除参数
            dal.ParameterManager.ClearParameter();
            
//添加参数
            dal.ParameterManager.AddNewInParameter("@Title""储存过程的标题有修改了————"50);    //nvarchar类型的参数,需要指定长度
            dal.ParameterManager.AddNewInParameter("@Content""嘻嘻哈哈");                 //ntext 类型的不需要指定长度
            dal.ParameterManager.AddNewInParameter("@AddedDate", DateTime.Now);           //日期型的
            dal.ParameterManager.AddNewInParameter("@Hits"3);                             //int型的

            dal.ParameterManager.AddNewInParameter(
"@NewsID"25);  //修改条件

            
//存储过程的名称要以Proc开头
            
//如果您不习惯Proc开头的话,那么需要修改数据访问函数库的内部函数。
            
//不建议使用xp_、sp_等开头,因为系统的存储过程的名称是以这些开头的。

            
//执行储存过程
            dal.ExecuteNonQuery("Proc_News_Mod");

            Response.Write(
"<BR>" + dal.ExecuteRowCount);

img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif            
判断是否出现异常 和 是否真的修改了一条数据#region 判断是否出现异常 和 是否真的修改了一条数据
            
//判断是否出现异常
            if (dal.ErrorMessage.Length > 0)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//出现了异常,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "修改数据的时候发生异常,请与管理员联系!");
                
return;
            }


            
//判断是否真的添加了一条数据
            
//ExecuteRowCount 会返回操作影响的行数(不包括select语句)
            if (dal.ExecuteRowCount != 1)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有正确添加一条数据,客户端弹出提示信息
                Functions.PageRegisterAlert(Page, "没有正确修改这条数据,请与管理员联系!");
                
return;
            }

            
#endregion

            
#endregion

 

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif         获取数据 #region 获取数据
        
protected void Btn_DataTable_Click(object sender, EventArgs e)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
string sql = "select * from News_NewsInfo";

            
//获取DataTable
            DataTable dt = dal.ExecuteFillDataTable(sql);

            
//获取DataSet
            DataSet ds = dal.ExecuteFillDataSet(sql);

            
//获取第一条记录的第一个字段
            sql = "select top 1 title from News_NewsInfo where NewsID = 21";
            
string NewsTitle = dal.ExecuteString(sql);

            
//获取第一条记录的多个字段,用于字段比较少的情况
            sql = "select top 1 title,Content,AddedDate,Hits from News_NewsInfo where NewsID = 21";
            
string[] NewsInfo = dal.ExecuteStringsBySingleRow(sql);

            
//获取每一条记录的第一个字段,有的时候会需要
            sql = "select hits from News_NewsInfo";
            
string[] HitList = dal.ExecuteStringsByColumns(sql);

            
//判断是否存在一条记录
            sql = "select top 1 1 from News_NewsInfo where title = '一个标题'";
            
if (dal.ExecuteExists(sql))
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//存在这条记录
            }

            
else
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
//没有找到这条记录
            }


        }

        
#endregion

 

 

    数据访问函数库的特点

1支持多种数据库。基于ado.net2.0 ,使用System.Data.Common.DbProviderFactory 来实现。

2调用方便、简捷。一般一行语句即可搞定。

3、对事务、储存过程的参数进行了封装,以达到简单好用的目的。

4、可以在内部拼接参数化的SQL语句,省去了在外部写参数化的SQL语句的烦恼。

5使用一个属性来代替异常处理,只需要检查这个属性值,即可知道是否发生异常。

6、产生异常的时候会记录下SQL语句(或者储存过程的名称)、错误描述、时间、网页即URL参数,以便于调试、修改错误。

 

这些代码应该写在哪一层?

    从语法的角度来讲,写在哪一层都可以通过编译。从流行的角度来讲呢,应该写在数据层。从我个人的角度来说呢,我是直接写在了aspx.cs文件里了,为什么要这么做呢?方便!

    另一个原因就是——我不知道要怎么分?不都写在aspx.cs文件里面写在哪呢?建立一个.cs文件,美其名曰“数据层”,写一个函数,把代码拷贝进去。然后在建立一个.cs文件,美其名曰“业务逻辑层”,再在这里调用刚写的那个函数,最后在.aspx.cs文件里面调用?这可就是纯粹为了分层而分层了。我觉得没有必要,呵呵。

 

    另外,就是这个操作习惯上的差别,让我走到了和主流不一样的道路!至少到目前为止,我还是觉得我的这个方向是没有错误的。

 

Ps:

    我的思路有一点另类,我的目的就是外部调用的时候一定要简单,不必要的“啰嗦”一定要去掉,而数据访问函数库的内部代码可以多一点,函数的功能可以细致一些(比如获取数据的地方,设置了好几个函数)。

 

    使用SQLHelp的时候,为什么要在外部实例化一个connection?为什么要在外部建立储存过程的参数?这么麻烦,为什么不能把这些都封装进去呢?所以我把这些都封装进去了。

 

 

变与不变

  neverlost 写的 2条路 代码生成 or 配置 》里有人问:“数据库字段修改了, sql 存储过程的参数修改了····如何通过你的说的可配置部分维护?”。我估计我们的思路应该差不多。

 

    

我说一下我的想法。就以上面的例子举例。假设News_NewsInfo表里面的“Title”字段想要改名,改成“NewsTitle”,那么我的代码要怎么改呢?

我只需要把

  dal.ParameterManager.AddNewInParameter("@Title", "参数化SQL语句的标题", 50);

改成

  dal.ParameterManager.AddNewInParameter("@NewsTitle", "参数化SQL语句的标题", 50);

 

就可以了,那么本质上我修改了什么呢?我修改了一个字符串的值!

 

    函数本身是不变的,变化的是参数值,就是那个字符串,就是那个字段名。不知道说道这里您有答案了没?就是说我可以把表名、字段名放在“配置”里面,用的时候读取出来,给函数的参数赋值,这样当字段名变化的时候,我只需要修改“配置”里的信息就可以了,不需要修改代码。

 

  您可能会问了,修改代码里的字符串是修改,修改“配置”也是修改,后者有什么优势吗?优势那可就大了。留一个想象的空间吧,暂时先不说了。

 

 

 源代码下载:http://www.cnblogs.com/jyk/archive/2008/07/29/1255891.html

相关文章
|
4月前
|
开发者 C# Android开发
震惊!Xamarin 跨平台开发优势满满却也挑战重重,代码复用、熟悉语言与性能优势并存,学习曲线与差异处理何解?
【8月更文挑战第31天】Xamarin 与 C# 结合,为移动应用开发带来高效跨平台解决方案,使用单一语言和框架即可构建 iOS、Android 和 Windows 原生应用。本文通过问答形式探讨 Xamarin 和 C# 如何塑造移动开发的未来,并通过示例代码展示其实际应用。Xamarin 和 C# 的组合不仅提高了开发效率,还支持最新的移动平台功能,帮助开发者应对未来挑战,如物联网、人工智能和增强现实等领域的需求。
56 0
|
4月前
|
SQL Java 关系型数据库
MyBatis-Plus 分页魅力绽放!紧跟技术热点,带你领略数据分页的高效与便捷
【8月更文挑战第29天】在 Java 开发中,数据处理至关重要,尤其在大量数据查询与展示时,分页功能尤为重要。MyBatis-Plus 作为一款强大的持久层框架,提供了便捷高效的分页解决方案。通过封装数据库分页查询语句,开发者能轻松实现分页功能。在实际应用中,只需创建 `Page` 对象并设置页码和每页条数,再通过 `QueryWrapper` 构建查询条件,调用 `selectPage` 方法即可完成分页查询。MyBatis-Plus 不仅生成分页 SQL 语句,还自动处理参数合法性检查,并支持条件查询和排序等功能,极大地提升了系统性能和稳定性。
68 0
|
5月前
|
算法 程序员
代码之舞:从逻辑之美到技术之艺
在数字世界的舞台上,代码不仅仅是冷冰冰的文字序列,而是充满韵律与美感的艺术。本文将带领读者走进编程的世界,探索如何通过逻辑的严谨性与创造性思维的结合,将代码变成一种独特的艺术形式。我们将一同见证技术与艺术如何交织在一起,创造出令人惊叹的作品。
|
存储 算法 区块链
Hash哈希竞猜游戏系统开发/区块链dapp游戏开发/规则玩法/项目案例/方案逻辑/成熟技术/源码程序
  哈希算法(Hash Algorithm)是一种将任意长度的消息映射为固定长度的消息摘要(Message Digest)的算法。哈希算法可以将任意长度的输入数据转换为固定长度的输出,
|
设计模式 小程序 测试技术
面对复杂问题时,系统思考助你理解问题本质
面对复杂问题时,系统思考助你理解问题本质
254 0
|
Shell
哈希竞猜游戏开发源码部署方案(成熟技术)
哈希竞猜游戏开发源码部署方案(成熟技术)
112 0
|
存储 编译器 Linux
C生万物 | 窥探数组设计的种种陷阱
数组在设计的时候为何会出现那么多纰漏?数组越界是如何导致的?,我们来一探究竟🔍
69 0
C生万物 | 窥探数组设计的种种陷阱
|
程序员 测试技术 开发者
以中国传统的孔子和老子的思想分析忍者代码
以中国传统的孔子和老子的思想分析忍者代码
677 0
以中国传统的孔子和老子的思想分析忍者代码
|
小程序 搜索推荐
聚合卡牌盲盒模式系统开发逻辑方案设计程序(成熟代码)
聚合卡牌盲盒模式系统开发逻辑方案设计程序(成熟代码)
316 0
|
SQL 缓存 监控
这波性能优化,太炸裂了!(下)
这波性能优化,太炸裂了!(下)
147 0
这波性能优化,太炸裂了!(下)
下一篇
DataWorks