数据库访问层,将所有的方法写成静态这是提高效率的一个很好的方法,现在要讨论的问题就是SqlConnection 和SqlCommand这二个对像,是否要静态的问题。
静态写法:
private static string strConnection = ConfigurationManager.ConnectionStrings["conString"].ToString();
private static SqlConnection con = new SqlConnection();
private static SqlCommand cmd = new SqlCommand();当要用到con这个静态字段的时候,用con.State判断一下,连接是否在打开状态,如果打开就用,不打开就不用,cmd对像用个CLEAR()的方法,用的时候清除一下!在B/S的应用中,我指的是网站。这样做的法,当存在并发的时候,会不会严重影响情能呢,因为只有一个连接对像,和一个命今对像。动态方法:
当要用到这个对像的时候,才创造这个对像,用完后,在关掉它。比如下面这个方法
public static object ExecuteScalar(string connString, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)
    {
        SqlCommand cmd = new SqlCommand();        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            cmd.Connection = conn;
            cmd.CommandText = cmdText;
            if (cmdParms != null)
            {
                foreach (SqlParameter parm in cmdParms)
                    cmd.Parameters.Add(parm);
            }
            object val = cmd.ExecuteScalar();
            cmd.Parameters.Clear();
            conn.Close();
            return val;
        }
    }还有是用using好呢,还是用TRY CATCH FINALLY请高手指教,谢谢!

解决方案 »

  1.   

    using其实就是try + finaly。没有必要用静态的,因为数据库会有连接池,new一个新的connection对象open时效率上不会开销很大的,而用静态可能会有并发问题(具体我没有试过,建议楼主试一下)而且效率上不见得一定有提高,所以建议不需要用静态的。
      

  2.   

    .net+sqlserver根本什么都不需要做,自己有链接池的
      

  3.   

    1.因为SQL有连接池的不需要
    2.using当用完了这对象之后会立即自动垃圾回收, 不用等到托管代码来回收.
    try catch只是错误捕获,你必须手动Dispose()你所创建的对象才能达到using的效果.
      

  4.   

    看到这一行就看不下去了,是垃圾无疑!
    //private static SqlConnection con = new SqlConnection();
      

  5.   

    private static  ……
    //viena 观察力真狠
      

  6.   

    private static SqlConnection con = new SqlConnection();
    private static SqlCommand cmd = new SqlCommand();
    ===============================
    写个多线程的测试一下你就晕了。private static string strConnection = ConfigurationManager.ConnectionStrings["conString"].ToString();
    ====================
    用得着.ToString();吗?
      

  7.   

    高手LZ,请重新构造一下您的DB基础类吧...可以参照MS的企业类库(带源代码的)MS的东西就是好,现在N多公司的基础库就是从那些库改进来的
      

  8.   

    初学者一般都会这么想。。我当初也是这么想的。。频繁打开数据连接多麻烦啊。。
    Eddie005(♂) №.零零伍 (♂) 
    在B/S的应用中,这样做的话,当存在并发的时候,会严重影响情能,甚至导致大规模的请求不响应!!!PS:为什么CSDN就有这么一些找抽贴啊。(不针对问题,针对个人素质)
      

  9.   

    用using也不好,应调用.Close方法释放回连接池~
      

  10.   

    谢谢大家,这些代码非本人所写,这个代码我是在网上搜到的,因为觉得有问题,所以才贴出来大家研究一下。这是一个人的BLOG上抄的,引用自
    http://blog.csdn.net/chenjinghua/archive/2006/06/23/825005.aspx
        本人只是一个小小的电工,只会修修电灯,换换日光灯,但对编程有强烈的爱好!所以提出来,大家研究研究!
        很感动,四个红星的进我的贴子,研究,谢谢你们啊!!
      

  11.   

    private static string strConnection = ConfigurationManager.ConnectionStrings["conString"].ToString();在ASP.2.0中我没用.ToString();竟然会报错,我想可能是OBJECT类型吧!
      

  12.   

    按楼主的标准,高手实在太多了
    1、想出用静态的人实在是太有创意了,PF!如果实在没把握SqlConnection的状态的话,用if(mySqlconn.State==close())mySqlconn.open();不行?
    2、好像没有人会一直保持mySqlconn.open()吧?本人一般人(非高手)在正常情况下都用try{}catch{}finaly{mySqlconn.close()}
    3、引用这样的一段代码来讨论,的确给大家的带来不少快乐:)
    谢谢楼主!
      

  13.   

    虽然俺不是高手
    但是俺知道这堆代码和想法都很垃圾其他的别人都说了
    检查State????
    呵呵~~~~
    效率是相当的差
    如果真的需要
    应该监视StateChange事件在CSDN混了这么长时间
    一般来说挑衅的题目内容往往很垃圾~~~~
      

  14.   

    我以为能写blog的人,一定是高手吧!高手写的数据访问层,一定要高手来讨论吧!结果引来了一片骂声.
       我开始通恨这个人,你想你不是高手,你就不要写blog,你写出blog就是让大家见的,结果你写的都是错了,我学起来,也跟者错,那你还写什么写,简直是误导初学者.
       以下是我写的数据层,时间关系,只写一些方法,如果还是引来一片骂声,我无话可说!
    using System;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;/// <summary>
    /// MS SQL 2000 数据访问层
    /// </summary>
    public class SqlDbCon
    {
        private static readonly string strConnection = "你的WEB.CONFIG配制节";
        public SqlDbCon()
        {
        }    #region 获得数据库连接对象    /// <summary>
        /// 获得数据库连接对象
        /// </summary>
        /// <returns>返回一个SqlConnection实例</returns>
        private static SqlConnection GetConnection()
        {
            SqlConnection con = new SqlConnection(strConnection);
            return con;
        }    #endregion    #region 获得数据库命令对象    /// <summary>
        /// 获得数据库连接命令
        /// </summary>
        /// <param name="strProcedureName">存储过程的名字</param>
        /// <param name="aryParameter">参数数组</param>
        /// <returns>返回一个SqlCommand实例</returns>
        private static SqlCommand GetCommand(string strProcedureName, params SqlParameter[] aryParameter)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = strProcedureName;
            foreach (SqlParameter sqlParameter in aryParameter)
            {
                cmd.Parameters.Add(sqlParameter);
            }
            return cmd;
        }    #endregion    #region 组装SqlParameter对象    /// <summary>
        /// 组装SqlParameter对象
        /// </summary>
        /// <param name="strParameterName">参数名字</param>
        /// <param name="sqlDbType">参数类型</param>
        /// <param name="intSize">参数字节</param>
        /// <param name="objValue">参数值</param>
        /// <returns>返回一个SqlParameter实例</returns>
        protected static SqlParameter BuildParameter(string strParameterName, SqlDbType sqlDbType, int intSize, object objValue)
        {
            SqlParameter sqlParameter = new SqlParameter(strParameterName, objValue);
            sqlParameter.SqlDbType = sqlDbType;
            sqlParameter.Size = intSize;
            return sqlParameter;
        }    #endregion    #region 执行带多个参数的存储过程    /// <summary>
        /// 执行带多个参数的存储过程
        /// </summary>
        /// <param name="strProcdureName">存储过程名</param>
        /// <param name="aryParameter">参数数组</param>
        /// <returns>如果成功返回true</returns>
        public static bool ExecuteProcedure(string strProcedureName, params SqlParameter[] aryParameter)
        {
            SqlConnection con = GetConnection();
            SqlCommand cmd = GetCommand(strProcedureName, aryParameter);
            cmd.Connection = con;        try
            {
                con.Open();
                cmd.ExecuteNonQuery();
                return true;
            }
            catch (SqlException e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                cmd.Dispose();
                con.Close();
            }
        }
    }
      

  15.   

    你的ExecuteProcedure
    我估计编译都通不过
    catch里面没有返回值
      

  16.   

    编译通过了,CATCH中是抛出用了个Throw,我试过,它会告诉你,问题出在什么地方!palts520() ( ) 信誉:100    Blog 
    二个三角的跟我差不多,一边休息去!
      

  17.   

    你把catch块去掉,它自然会抛出异常
      

  18.   

    二个三角的跟我差不多,一边休息去!
    ----〉偷偷的告诉你
    CSDN一个三角的高手有很多
      

  19.   

    用不用静态的无所谓,如果不是及连及时释放的形式,那么必须要实现连接池;当目标数据库的连接资源缺乏的时候用的上,比如正版的 oracle 的连接数需要购买;
      

  20.   

    TMD真怪自己不是高手
    要我星星月亮一打了
    真想好好教育教育某人
    “不耻下问”的典故
    何况,除了本人
    回帖的还偏偏都是比某人有能耐的不耻下问不懂
    不耻上问又不明白
      

  21.   

    Catch个人认为还是留着
    建议加一个Exception类我的程序里面没有把系统异常直接扔给客户的~~~~
      

  22.   

    这个catch留不留看个人设计风格,一般来说最底层的函数可以不try,这个ExecuteProcedure可以不try,在调用该方法的过程内捕获;
      

  23.   

    lovefootball(蟑螂(生活就是扯淡--做人要放低姿态)) 没人SB到把自个的错误抛给别人SEE,这样不是给HACKER机会,这当然是在调试的时候,正试运行的时候,会写自定义的Exception类,抛到错误的页面!不错错误的原因!没CATH当然也会,可这样你的软件就不完没,最好也要搞个CATC空块
      

  24.   

    忍不住又回来说两句private static string strConnection = ConfigurationManager.ConnectionStrings["conString"].ToString();在ASP.2.0中我没用.ToString();竟然会报错,我想可能是OBJECT类型吧!_________________不是object对象,而是ConnectionStringSettingsCollection对象
    它的两个属性ConnectionString和ProviderName你一定也不知道
    才会用ToString()方法
    可见外行!
    还有,何必要这样取连接子串呢
    难道阁下这样的高手一点向后兼容的观点都没有
      

  25.   

    /*
    没人SB到把自个的错误抛给别人SEE,这样不是给HACKER机会,这当然是在调试的时候,正试运行的时候,会写自定义的Exception类,抛到错误的页面!不错错误的原因!没CATH当然也会,可这样你的软件就不完没,最好也要搞个CATC空块
    */我服了,没话可说~
      

  26.   

    to S.F.(chinasf.cnblogs.com) :/*
    这个catch留不留看个人设计风格,一般来说最底层的函数可以不try,这个ExecuteProcedure可以不try,在调用该方法的过程内捕获;
    */
    这里用try,是为了在finally里面调用连接.Close()
      

  27.   

    数据库连接基本上大家都会碰到类似的问题,如果你是在考虑并发性上面,try 和 using差别不大,主要考虑并发数量(连接池),在连接字符串可以申明你的连接数量,池化功能,.net已经做好.你使用时只需保证有了open操作完后close就可以,这里的open(如果是第一次将创建连接池,以后则是从池中取出)而close也并非马上关闭.
    1.关心设置连接池大小
    2.保存操作的一致性(有open,就别忘记close)对于数据库访问层(断开模式和连接模式)都有可取之处,根据需求不同而定(PetShop是个好例子但未必都一样它只是指导了B/S编程方法)
      

  28.   

    lovefootball(蟑螂(生活就是扯淡--做人要放低姿态))没人SB到把自个的错误抛给别人SEE,这样不是给HACKER机会,这当然是在调试的时候,正试运行的时候,会写自定义的Exception类,抛到错误的页面!不错错误的原因!
    ----〉
    我看到的代码确实是把异常直接抛给了别人
    呵呵如果说你还会完善现在的程序
    那这个程序应该是没问题
    反正以后还会完善
    具体到啥程度别人也不知道
    也许比MS的框架还要好很多
    中国的软件未来就靠楼主了
    我看你行~~~
    我支持你~~~
      

  29.   

    编译通过了,CATCH中是抛出用了个Throw,我试过,它会告诉你,问题出在什么地方!palts520() ( ) 信誉:100    Blog 
    二个三角的跟我差不多,一边休息去
    ---------------------------------
    我 是刚玩这个
    可不能这么说哈
      

  30.   

    感觉是不是在讨论问题啊,还是讨论lz的问题上来吧
    在做数据访问层上还需要深入学习和实践.不针对具体某个类,抽象出来.
    如(连接模式)
    public interface IUserDispose
    {
        void Dispose(IUserDisposeCallBack handler);
    }public interface IUserDisposeCallBack
    {
        Dispose(SqlDataReader read);
    }UserDispose:IUserDispose
    {
        public void Dispose(IUserDisposeCallBack handler)
        {
             SqlCommand cmd=null;
             SqlDataReader read=null;
             try
             {
                 cmd=....
                 cmd.Connection.Open();
                 handler.Dispose(read);
             }
             catch(SqlException ex)
             {
                myLog.Write("yearself message",ex);
             }
             finally
             {
                 if(cmd!=null&&cmd.Connection.State!=ConnectionState.Close)
                     cmd.Connection.Close();
             }
        }
    }这里只是一个小例子(模板方法),希望lz针对接口编程,这里当然也可以用.net委托来实现
    在实现CallBack的自由度就大了(扩展)可以自由定制
    刚才看了
    protected static SqlParameter BuildParameter(string strParameterName, SqlDbType sqlDbType, int intSize, object objValue)
        {
            SqlParameter sqlParameter = new SqlParameter(strParameterName, objValue);
            sqlParameter.SqlDbType = sqlDbType;
            sqlParameter.Size = intSize;
            return sqlParameter;
        }
    有时可以不申明类型
    cmd.Parameters.Add("参数",值);
      

  31.   

    连接改静态的话 并发访问肯定会出问题。因为在一个连接上执行一个CMD的时候,数据库会分配一个锁资源给这个连接,这时如果又在这个连接上执行新CMD,肯定会抛出异常。解决的方法是对访问这个静态连接加锁(lock(){...}或者用Metux或Monitor),但我们知道windows的锁效率很低,导致使用静态的连接效率也很低,还不如动态建连接。
      

  32.   

    将数据访问单独封装成一层
    为的是维护方便
    严格地说对效率会产生负面影响
    对于B/S程序的数据访问目前还没有好的解决办法
    虽然有连接池技术
    但对于大并发请求,数据库依然会很吃力
    但是可以采用象数据缓存的方法来绕开对数据库的多次相同结果的访问
    Oracle在大并发的情况下表现比SqlServer好(本人自己做的测试)
    一个重要的原因就是
    Oracle本身就带有缓存技术
    毕竟从内存读取数据要比磁盘读文件快很多象楼主那样有不要缓存
    又想要高性能
    还不如不要封装数据访问层
    直接将数据访问代码写入每一个需要访问数据库的方法中
    而且务必要调用close()方法
    且保证close()方法在方法体中任何执行路径能够被访问到
      

  33.   

    wfyfngu(SecureCRM) ( ) 您好,刚见到你的贴子,事实上,我以前也把数据连接封装在业务层,不过,有个问题,要现比较多的复代码,还是加一个数据层,这样写起来比较方便!还有补充一点,一定要用CATCH的,用CATCH就是保证应用程序的建康!准备结贴.viena(维也纳nn) ( ) 信誉:100    Blog  发言最积极 +40
      

  34.   

    真是失望,有机会最好面对面的讨论
    针对接口编程是为了有良好的扩展性.
    而对net数据库编程中的注意点也都说了.
    不知道在贴中的有没有处理过每秒100个并发请求.
    每小时采集10万数据信息,很多时候要实践来说话.