当前位置: 代码迷 >> ASP >> ASP.NET系统开发(1):层层递进之SQLHelper助手类的持续优化
  详细解决方案

ASP.NET系统开发(1):层层递进之SQLHelper助手类的持续优化

热度:274   发布时间:2012-08-13 13:21:53.0
ASP.NET系统开发(一):层层递进之SQLHelper助手类的持续优化

       

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谢谢,我会的