ASP.NET开发中的三层开发思想指的是UI层(界面显示层),BLL层(业务逻辑层),DAL层(数据访问层)三层,三层之间通过函数的调用来达到降低耦合,易于系统维护的目的,SQLHelper助手类的主要作用在于接收并执行来自各个数据表累传来的sql语句或存储过程。一般的SQLHelper类中主要包括以下几个函数功能:
1.执行不带参数的增删改方法
2.执行带参数的增删改方法。
3.执行不带参数的查询方法。
4.执行带参数的查询方法。
作为一个程序员SQLHelper类编写的好坏不仅影响着系统的可维护性的强弱,而且它更体现的是一个编程人员的职业素质。一个程序员的成长过程中必然要经过代码的锤炼,代码见证了一个编程人员的成长历程,下面通过不同版本的SQLHelper类来向大家展示一个良好的SQLHelper助手类是怎样炼成的:
一、初涉江湖版(A级代码)
namespace dal { public class SQLHelper { /// 执行带参数的增删改方法 public int ExecuteNonQuery(string sqltext,CommandType ct,SqlParameter [] paras) { string strconn ="server=YCH-PC;database=newssystem;uid=sa;pwd=1314517"; SqlConnection conn = new SqlConnection(strconn); //定义一个数据库连接对象(下同) conn.Open(); //打开数据库连接(下同) SqlCommand cmd = new SqlCommand(sqltext , conn ); //实例化一个命令对象(下同) cmd.CommandType = ct; //指定命令类型(下同) cmd.Parameters.AddRange(paras); //增加参数(下同) int res = cmd.ExecuteNonQuery(); //执行命令(下同) conn .Close (); //关闭数据库连接(下同) return res; //返回执行结果(下同) } /// 执行不带参数的增删改方法 public int ExecuteNonQuery(string sqltext, CommandType ct) { string strconn = "server=YCH-PC;database=newssystem;uid=sa;pwd=123456"; SqlConnection conn = new SqlConnection(strconn); conn.Open(); SqlCommand cmd = new SqlCommand(sqltext, conn); cmd.CommandType = ct; int res = cmd.ExecuteNonQuery(); conn.Close(); return res; } /// 执行不带参数的查询方法 public DataTable ExecuteQuery(string sqltext, CommandType ct) { string strconn = "server=YCH-PC;database=newssystem;uid=sa;pwd=123456"; SqlConnection conn = new SqlConnection(strconn); conn.Open(); SqlDataReader sdr ; DataTable dt=new DataTable (); SqlCommand cmd = new SqlCommand(sqltext, conn); cmd.CommandType = ct; sdr = cmd.ExecuteReader(); dt.Load(sdr); conn.Close(); return dt ; } /// 执行带参数的查询操作 public DataTable ExecuteQuery(string sqltext, CommandType ct, SqlParameter[] paras) { string strconn = "server=YCH-PC;database=newssystem;uid=sa;pwd=123456"; SqlConnection conn = new SqlConnection(strconn); conn.Open(); SqlDataReader sdr; DataTable dt = new DataTable(); SqlCommand cmd = new SqlCommand(sqltext, conn); cmd.CommandType = ct; cmd.Parameters.AddRange(paras); sdr = cmd.ExecuteReader(); dt.Load(sdr); conn.Close(); return dt ; } } }
二、血雨腥风版(AA级代码)
从上面的代码中我们可以很明显的看出,各个函数中数据库连接字符串、连接对象以及数据库连接的打开和关闭都是相同的,代码的重复往往是糟糕代码的标志,下面我们就通过代码改造来减少代码冗余,提高代码的复用率。代码的主要改动部分就是针对上述相同的代码片段进行的:
namespace dal { public class SQLHelper { private SqlConnection conn = null; private SqlCommand cmd = null; /// 实例化SQLHelper类的时候便实例化一个数据库连接 public SQLHelper() { string connStr = "server=YCH-PC;database=newssystem;uid=sa;pwd=123456"; conn = new SqlConnection(connStr); } /// 打开数据库连接 private SqlConnection GetConn() { if (conn.State == ConnectionState.Closed) { conn.Open(); } return conn; } /// 关闭数据库连接 private void OutConn() { if (conn.State == ConnectionState.Open) { conn.Close(); } } /// 执行不带参数的增删改操作 public int ExecuteNonQuery(string cmdText, CommandType ct) { cmd = new SqlCommand(cmdText, GetConn()); cmd.CommandType = ct; int res = cmd.ExecuteNonQuery(); OutConn(); return res; } /// 执行带参数的增删改方法 public int ExecuteNonQuery(string sqltext, CommandType ct, SqlParameter[] paras) { SqlCommand cmd = new SqlCommand(sqltext, GetConn()); cmd.CommandType = ct; cmd.Parameters.AddRange(paras); int res = cmd.ExecuteNonQuery(); OutConn(); return res; } /// 执行不带参数的查询方法 public DataTable ExecuteQuery(string sqltext, CommandType ct) { DataTable dt = new DataTable(); SqlCommand cmd = new SqlCommand(sqltext, GetConn()); cmd.CommandType = ct; SqlDataReader sdr = cmd.ExecuteReader(); dt.Load(sdr); sdr.Close(); OutConn(); return dt; } /// 执行带参数的查询操作 public DataTable ExecuteQuery(string sqltext, CommandType ct, SqlParameter[] paras) { DataTable dt = new DataTable(); SqlCommand cmd = new SqlCommand(sqltext, GetConn()); cmd.CommandType = ct; cmd.Parameters.AddRange(paras); SqlDataReader sdr = cmd.ExecuteReader(); dt.Load(sdr); sdr.Close(); OutConn(); return dt ; } } }
三、炉火纯青版(AAA级代码)
通过”瘦身行动“,现在的代码是不是比第一版代码清晰了很多呢?但这还不是最后的结果。有的人会提出这样的问题:把连接字符串写在SQLHelper类中,如果我现在要更换数据库,那岂不是要对SQLHelper助手类进行更改,这样似乎不符合我们”开放扩展,关闭修改“的要求。另外在执行查询过程时需要先关闭SqlDataReader再关闭数据库连接,这样在代码中也出现了重复,能不能再进一步对代码进行改造来解决这两个问题呢?下面我们就上述两个问题对代码进行进一的步改造: 解决更换数据库的问题我们采取的方法是将连接字符串写在配置文件中,具体步骤为:
1. 双击web层中Web.config文件,配置文件中的相关内容将会出现。
2. 找到<connectionStrings>和</connectionStrings>,在二者之间添加如下内容:<add name=<add name=连接字符串 connectionString ="server=YCH-PC;database=newssystem;uid=sa;pwd=具体的登陆密码"/>
3. 修改SQLHelper类中的相关代码如下:
namespace dal { public class SQLHelper { private SqlConnection conn = null; private SqlCommand cmd = null; private SqlDataReader sdr = null; public SQLHelper() { string strconn = ConfigurationManager.ConnectionStrings["strconn"].ConnectionString; conn = new SqlConnection(strconn ); } private SqlConnection GetConn() { if (conn.State == ConnectionState.Closed) { conn.Open(); } return conn; } //关闭数据库连接 private void OutConn() { if (conn.State == ConnectionState.Open) { conn.Close(); } } /// 执行不带参数的增删改SQL语句或存储过程 public int ExecuteNonQuery(string cmdText, CommandType ct) { int res; try { cmd = new SqlCommand(cmdText, GetConn()); cmd.CommandType = ct; res = cmd.ExecuteNonQuery(); } catch (Exception ex) { throw ex; } finally { OutConn(); } return res; } /// 执行带参数的增删改SQL语句或存储过程 public int ExecuteNonQuery(string cmdText, SqlParameter[] paras, CommandType ct) { int res; try { cmd = new SqlCommand(cmdText, GetConn()); cmd.CommandType = ct; cmd.Parameters.AddRange(paras); res = cmd.ExecuteNonQuery(); } catch (Exception ex) { throw ex; } finally { OutConn(); } return res; } /// 执行不带参数的查询SQL语句或存储过程 public DataTable ExecuteQuery(string cmdText, CommandType ct) { DataTable dt = new DataTable(); cmd = new SqlCommand(cmdText, GetConn()); cmd.CommandType = ct; using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { dt.Load(sdr); } return dt; } /// 执行带参数的查询SQL语句或存储过程 public DataTable ExecuteQuery(string cmdText, SqlParameter[] paras, CommandType ct) { DataTable dt = new DataTable(); cmd = new SqlCommand(cmdText, GetConn()); cmd.CommandType = ct; cmd.Parameters.AddRange(paras); using (sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { dt.Load(sdr); } return dt; } } }
经过对代码的再次改造,不但代码的重复率大大降低,而且如需更换数据库,只要在配置文件中更改相应的连接字符串就可完。在编写查询(包括带参数的和不带参数的查询方法)方法时,用using方法,在关闭SqlDataReader对象的时候同时关闭与之相关联的数据库连接,避免了try catch语句的使用,代码更加简洁。经过三次改造,SQLHelper助手类的变身就此完成。
- 36楼xiaokui00821分钟前
- 理解最重要,还是要自己在项目中多实践。顶了,继续加油。
- Re: a1314517love20分钟前
- 回复xiaokui008n谢谢,我会加深理解的..
- 35楼sunliduan21分钟前
- 江湖之路颇多坎坷啊。。。
- Re: a1314517love21分钟前
- 回复sunliduann是啊,人在江湖身不由己
- 34楼aboy12322分钟前
- 层层递进啊
- Re: a1314517love22分钟前
- 回复aboy123n是的,层层递进
- 33楼haibingongyuan23分钟前
- 期待下一篇文章
- Re: a1314517love23分钟前
- 回复haibingongyuann好的,我会努力的
- 32楼jyhye24分钟前
- 代码整齐点就好了,如果注释详细点对我这样的初学者很有好处的。非常好噻
- Re: a1314517love23分钟前
- 回复jyhyen实在抱歉,我也想把排版排好,不过我试了一上午,在编辑页面排好的到发表后也就成这样了,谢谢你的肯定,我会更努力的
- 31楼yangmadao25分钟前
- 虽然不懂,但还是顶一个
- Re: a1314517love24分钟前
- 回复yangmadaon谢谢,多看点关于编程的就能明白了
- 30楼yuyunli198926分钟前
- 很不错!
- Re: a1314517love25分钟前
- 回复yuyunli1989n谢谢师姐,多多指教啊师姐!
- 29楼haixianshichang27分钟前
- 代码片段有点长,再精简些比较好
- Re: a1314517love27分钟前
- 回复haixianshichangn嗯,谢谢指教
- 28楼zhang_ying11230分钟前
- 顶一个~
- Re: a1314517love28分钟前
- 回复zhang_ying112n小老乡,给力
- 27楼zhaohuanhuanjiuqi30分钟前
- 代码还能如此简洁。。。
- Re: a1314517love30分钟前
- 回复zhaohuanhuanjiuqin其实还可以更简洁的
- 26楼lypf1990091232分钟前
- 师傅 徒弟支持````````n 加油
- Re: a1314517love30分钟前
- 回复lypf19900912n哈哈,谢谢徒弟!
- 25楼xqf30934分钟前
- 层层优化,[e01]
- Re: a1314517love32分钟前
- 回复xqf309n逐步深入...
- 24楼lidaasky35分钟前
- 不错不错,层层递进
- Re: a1314517love34分钟前
- 回复lidaaskyn多谢,达哥哈哈
- 23楼a1314517love36分钟前
- 其实代码可以更加优化
- Re: a1314517love35分钟前
- 回复a1314517loven继续加油!
- 22楼zhanglianhai55538分钟前
- 虽然没看懂,但我支持你!
- Re: a1314517love37分钟前
- 回复zhanglianhai555n海哥给力,谢啦哈哈
- 21楼qibingliandui39分钟前
- 路过,差强人意
- Re: a1314517love38分钟前
- 回复qibinglianduin谢谢,欢迎经常来访
- 20楼akkzhjj40分钟前
- 师父厉害
- Re: a1314517love39分钟前
- 回复akkzhjjn徒弟过奖,呵呵,你们到明年这会可定会比我们好
- 19楼lbq61361340分钟前
- 很好,很强大啊!
- Re: a1314517love40分钟前
- 回复lbq613613n强哥过奖,嘿嘿
- 18楼tcl_666641分钟前
- 非查询方法也可以使用using语句,使得代码进一步简化nusing (cmd = new SqlCommand(cmdText, GetConn())) {n cmd.CommandType = ct;n cmd.Parameters.AddRange(paras);nn tryn {n res = cmd.ExecuteNonQuery();n }n catch (Exception ex)n {nn throw new Exception("执行带参数的增删改SQL语句或者存储过程时出错," + ex.Message);n }n }
- 17楼llhhyy198943分钟前
- 从你这篇文章,可以看出对面向对象的思想有很大的理解哈。对高内聚低耦合,反射,开闭原则都应用的游刃有余
- Re: a1314517love41分钟前
- 回复llhhyy1989n师姐过奖了,多多指教啊师姐!
- 16楼qiulongtianshi44分钟前
- [code=csharp]n SqlConnection conn = new SqlConnection(strconn); //定义一个数据库连接对象(下同) n conn.Open(); //打开数据库连接(下同) n[/code]n写的内容很好,非常的好,格式这样有点不好,尽量在一行,你发表了博客自己应该看一下效果,你的感觉就是读者的感觉。
- Re: a1314517love44分钟前
- 回复qiulongtianshin嗯,不过似乎排版有点困难,在编辑页面明明很好,但是一发表出来就不行,我已经改过好多次排版了,还是不行,有什么好的方法吗师哥?
- 15楼sunqing031649分钟前
- 顶一个
- Re: a1314517love45分钟前
- 回复sunqing0316n谢谢,欢迎常来
- 14楼wangyongxia92153分钟前
- 好好好!
- Re: a1314517love49分钟前
- 回复wangyongxia921n评语精练,哈哈
- 13楼leimengyuanlian57分钟前
- 很强大,
- Re: a1314517love55分钟前
- 回复leimengyuanliann谢谢,不过你的逗号似乎是告诉我你还有话没说啊,呵呵
- 12楼yjjm19901小时前
- 嗯,写得很好!学习了!sqlhelper类还可以加入有执行事务的方法、批量导入的方法。
- Re: a1314517love59分钟前
- 回复yjjm1990n谢谢,说实话我没有用过你说的那两种,不过我很想尝试一下,多对指教啊
- 11楼wwwwenhuan1小时前
- 不错
- Re: a1314517love1小时前
- 回复wwwwenhuann谢谢...
- 10楼shanpaodajun1小时前
- 这只是后台代码编写的一小部分,前台也很重要
- Re: a1314517love1小时前
- 回复shanpaodajunn嗯,现在这部分只是整个系统的一小部分,没有全部写出
- 9楼happy09li1小时前
- 这只适合一种数据库,应该做多数据的
- Re: a1314517love1小时前
- 回复happy09lin是的,应用抽象工厂加配置文件的方法可以解决更换数据库的问题,时间关系没有写详细
- Re: happy09li1小时前
- 回复a1314517loven可以试试,,用到多数据库时,就方便了
- 8楼zhangyingjie8182121小时前
- 师哥,加油
- Re: a1314517love1小时前
- 回复zhangyingjie818212n好的,谢谢
- 7楼huanjileaimeidan1小时前
- 加油!
- Re: a1314517love1小时前
- 回复huanjileaimeidann好的,谢啦小师妹,哈哈
- 6楼beijiguangyong1小时前
- 没有考虑事务哦,亲~
- Re: a1314517love1小时前
- 回复beijiguangyongn额,是的!下次注意,欢迎常来啊师哥
- 5楼laner05151小时前
- 看出来了,老江湖啊
- Re: a1314517love1小时前
- 回复laner0515n我是被逼上梁山的,呜呜
- 4楼nanshangongyuan1小时前
- 排版有点问题,不过写的还可以
- Re: a1314517love1小时前
- 回复nanshangongyuann排版很是让人头疼的事,谢谢
- 3楼penglaidao1小时前
- 如果能有一个系统的三层调用更好
- Re: a1314517love1小时前
- 回复penglaidaon嗯,这只是连载文章的第一篇,在接下来的文章中我会简单的写一个三层调用的小例子,期待指教啊
- 2楼yantaifuge1小时前
- 学习了。。。
- Re: a1314517love1小时前
- 回复yantaifugen欢迎常来
- 1楼dongyafeihuang1小时前
- 不错的文章,加油
- Re: a1314517love1小时前
- 回复dongyafeihuangn谢谢,我会的