ms-help://MS.NETFrameworkSDK.CHS/cpguidenf/html/cpconserveractivation.htm

解决方案 »

  1.   

    实现很简单,但是我不想说,因为这种方式不是正确的"整个应用程序中只有一个连接数据库的Connection实例"这种想法是错误的请在MSDN中参考“连接池”的相关内容:
    ms-help://MS.VSCC/MS.MSDNVS.2052/Vbcon/html/vburfIntroductionToADOConnectionDesignTools.htm或者参考这个贴子:
    http://expert.csdn.net/Expert/topic/1517/1517079.xml?temp=.8440515
      

  2.   

    如果你保持整个应用程序一个连接实例,那么就会造成瓶颈并且多数没有访问数据库的时候,这个实例占用了连接资源对于数据库这种昂贵的资源,应该用完就释放通常正确的做法是每一次连接数据库都new一个连接对象(实际上new这个对象本身并不会耗费多少资源,连接是从连接池获得,并不意味着每一次new连接对象都会创建数据库连接),使用完之后就Close并释放,使连接回到连接池。数据库连接和连接对象(SqlConnection)很类似,但是它们不是完全一致的,连接对象封装一个数据库连接,但是连接对象的创建和消亡不意味着数据库连接的创建和消亡。对连接的管理应该交给连接池,而不是自己手动来控制。
      

  3.   

    连接池不是为每一个实例设置连接数实际上对于ADO.Net的连接池来说,只要是相同的连接字符串,都会被放在同一个池中所以只要保证连接字符串相同,那么就可以共用一个连接池,虽然你感觉不到,但连接池是一直存在并使用的,只要你用ADO.Net,实际上你已经使用了连接池,只是你没感觉到而已,一般的开发,可以不用管连接池的存在,但是连接对象的使用原则必须遵守,这样才能保证连接池的效率,用一个实例来连接数据库是不好的做法,实际上并不会提高效率。连接池设置的连接数是指这个池中的最小和最大连接数。
      

  4.   

    不同的连接字符串会存放在不同的连接池中,ADO.Net会帮你管理连接串不同的话,是不能用一个连接池的实际上你自己根本不用管,ADO.Net会帮你处理好,如果你有几个连接串,它就会帮你维护几个连接池,并且保证里面的连接数量能够满足你的应用(如果不手动设置最大和最小连接数的话)你可以做一个测试,用ADO.Net连接数据库,第一次创建Connection对象花费时间和以后创建同样连接串的Connection对象花费的时间,你会发现后者会快几倍甚至几十倍,原因就是后来的连接是从连接池或取的。连接池是这样运作的:
    1、创建Connection对象的时候,ADO.Net会根据连接串查看是否连接池,没有就创建
    2、查看连接池中是否有闲置未用的连接,是的话直接取一个交给Connection对象,没有就创建一个数据库连接
    3、Connection对象调用Close方法的时候,数据库连接会回到连接池,并保持闲置状态4、连接池会定期维护连接池,如果闲置连接太多,可能会利用某些算法来释放一些,以节省资源所以,每次使用完Connection对象都需要释放,让连接回到连接池,让其他需要的地方使用,这样才能使资源的使用达到最优化。
      

  5.   

    这么说,如果我想只要有一个连接供我调用的话,只要将“Max(Min)Pool Size”都设置
    成“1”就可以了,对吧?这样所有要连接数据库的东东都会去使用那个唯一存在的连接资源,是不是?
      

  6.   

    是的,但是这样不好,这样的话一个连接在使用的时候,其他的数据库访问都要等待,会造成你系统的瓶颈一般的应用不用设置“Max(Min)Pool Size”,用默认值就好
      

  7.   

    在程序中使用单一实例是必须的,至于为什么,我就不多将了。下面我将自己平时应用Singleton模式做的单一实例的连接代码给你看一下:
    public class PublicDataClass
    {
        private static  PublicDataClass m_publicData=null;
        public          SqlConnection     m_connection     =null;
    private PublicDataClass()
    {
    //
    // TODO: Add constructor logic here
    //
    }
    public static PublicDataClass CreateInstance()
    {
    //-------------------->创建单一实例<--------------------
    if(m_publicData==null)
    {
    try
    {
    m_publicData=new PublicDataClass();
    }
    catch(Exception)
    {
    m_publicData=null;
    }
    }
    return m_publicData;
                //-----------------------------------------------------
    }
    public void SetConnectionString(string str)
    {
    //------------->设置连接字符串<----------------------
    if(str.Trim()=="") throw new Exception("连接字符串为空!");  
    try
    {
    if(m_connection==null) 
    {
    m_connection =new SqlConnection(); 
    }
    else
    {
    if(m_connection.State ==ConnectionState.Open) m_connection.Close();  
    }
    m_connection.ConnectionString =str;
    m_connection.Open();
    m_connection.Close(); 
    }
    catch(Exception)
    {
    throw new Exception("不能连接数据库!"); 
    }
    //---------------------------------------------------
    }
    }
    在程序的其他模块中只需要调用以下代码即可:
    PublicDataClass m_pubdata=PublicDataClass.CreateInstance();
    if(m_pubdata.m_connection==null)
    {
      str=m_pubdata.ReadConnectionString(); 
      m_pubdata.SetConnectionString(str); 
    }
    在模块退出时:
    m_pubdata=null;
      

  8.   

    可以把你的代码改成这样:public class PublicDataClass
    {
    private static  PublicDataClass m_publicData=null;
    // public          SqlConnection     m_connection     =null; 不要保留唯一的连接实例
    private string _connectionStr = null; //保留连接字符串
    //用属性封装对字段的访问,这是.Net组件设计的一个准则,这样方便以后的维护
    public string ConnectionString
    {
    get {
    return _connectionStr;
    }
    set {
    //------------->设置连接字符串<----------------------
    if(str.Trim()=="") throw new Exception("连接字符串为空!");  
    _connectionStr = value;
    //---------------------------------------------------
    }
    } //获取连接对象,每次都返回一个新创建的连接,这样才能最有效率的使用连接池
    public SqlConnection Connection
    {
    get {
    try
    {
    SqlConnection con = new SqlConnection();
    connection.ConnectionString =value;
    con.Open();
    }
    catch(Exception)
    {
    throw new Exception("不能连接数据库!"); 
    }
    }
    } private PublicDataClass()
    {} //用属性代替方法,这是.Net中的做法
    public static PublicDataClass Instance
    {
    get {
    if( m_publicData==null )
    try
    {
    m_publicData=new PublicDataClass();
    }
    catch(Exception)
    {
    m_publicData=null;
    }
    return m_publicData;
    }
    }
    }
      

  9.   

    使用的时候:
    PublicDataClass m_pubdata=PublicDataClass.CreateInstance();
    if(PublicDataClass.Instance.ConnectionString==null)
    {
      PublicDataClass.Instance.ConnectionString=m_pubdata.ReadConnectionString();
    }然后使用:
    PublicDataClass.Instance.Connection去连接数据库
      

  10.   

    Sorry
    PublicDataClass m_pubdata=PublicDataClass.CreateInstance();
    这句可以不要了
      

  11.   

    我想问,连接池里到底有多少连接?如果说它仅仅只有1个连接的话,我倒是愿意采纳
    你的建议,可是如果是存在多个相同连接,我看这已经和我的初衷背道而驰了,因为
    数据库的连接毕竟是有限的,因此我们必须用最少的连接去完成很多事情(1个连接),
    如果我把一个WebService的功能定义为访问某数据库的话,那么我要求就是只存在一个
    连接,用它去访问数据,至于那些调用WebService的客户端(即,某某应用页面)则也只是
    通过一个连接去访问数据库,而不是另外又多建多条相同的连接,那样做更会消耗我们的
    数据库的现有资源的。
      

  12.   

    timmy3310(tim) :
       我对你的做法持不同的意见:
       当使用你的方法后,每一次模块去调用一个连接时,就会创建一个新的连接,也就是说,如果你不进行立即释放的话,在这个单一实例的数据类中就会存在多个连接实例,而如果单一实例中还存在很多的数据表,而由于类的唯一性决定了这些数据表的唯一性,请问,这些数据表该与那个连接进行对应呢?另外,模块每次启动时只需要引用一个早已经存在的连接对象(只须创建一次),这样的技术难道还比不上你每次启动模块时还要去什么新建一个连接对象快吗?你不要说什么连接池技术,就是请来比尔.盖茨也没用。我上面的做法可以完成保证只有一个连接,因为连接字符串是打包在这个数据类中,只能读取,不能更改
    if(m_pubdata.m_connection==null)
    {
      str=m_pubdata.ReadConnectionString(); //对一个XML文件进行读取(存放连接字符串)
      m_pubdata.SetConnectionString(str); 
    }另外还有一点://用属性代替方法,这是.Net中的做法
    我对这点也有不同的意见:
    好象只听说过:用属性代替数据成员的说法,并且这种做法也不是.NET的什么新创,而是OO的思想。我在上面的数据类中将连接对象没有做成属性,只是为了偷懒而已。
      

  13.   

    to wandao() :
       如果我把你所提供的方法看成一个WebService服务的话,
    即,创建实例的过程不是在WebService里面,而是放在其
    应用页面中去的话,我该怎样创建这个唯一的实例呢?
    你要知道,在创建应用程序的时候,我们通常是Reference(引用)
    一个Web服务,我试过了,在那种情况下,不能够调用你前面
    重新定义的构造函数CreateInstance(),那样的话我不是就不能够
    创建一个Singelton了吗?你有什么办法可以解决它吗?
      

  14.   

    to timmy3310(tim) :
       我上面的做法不是在WebService里面,而是在一个程序内部多个功能模块共享的数据类。
    如果你要在一个WebService里面实现这样的效果,可能稍微变通一下:
       将类的构造函数改成static形式:
       public static PublicDataClass()
       {
       }
       你用这种方式再试试看。
       另外,刚才如果我所发的帖子对你有什么不敬的话,还请见谅!!!
       学海无边,每个人都还有不足的地方!!!
      

  15.   

    To wangchinaking(助人为乐是快乐之本) 
    连接池里面存在多少个连接,这要看你的应用,如果你的应用不是很频繁的访问数据库,那么有可能从头到尾只有一个连接,但是如果很频繁,那就说不定了,但是你可以通过设置Max Pool Size来限制最大连接数如果只有一个连接,而且数据库访问很频繁的话,你的程序会很迟缓,因为当一个线程访问数据库的时候,其他的线程不得不等待,而Web Service和Web Application的应用天生就是多线程的。如果100个用户同时在线,用一个连接访问数据库,那么一个人查找的时候,就有99个人在等待。我们来就这个来举个例子,如果100个人在线,每个人访问数据库的时间是5%,也就是说平均有20分之一的人可能会同时访问,这时候,如果连接池有5个连接,那么就可以满足要求了。实际上不是说每创建一个Connection对象,就会创建一个数据库连接,这我已经说了很多遍了;一般的应用,只要在前期的性能测试中获取一个服务器能支撑的连接最大值,然后设置Max Pool Size就可以保证服务器的资源,对于已存在的连接,如果正确的使用,那么连接池绝对会帮你让它发挥最大作用。其实你可以用Windows2000的“Perfermance”查看性能指数,一般来说,一台中等的Server支持100个人在线是没问题的
      

  16.   

    To wandao() 
    --
    "模块每次启动时只需要引用一个早已经存在的连接对象(只须创建一次),这样的技术难道还比不上你每次启动模块时还要去什么新建一个连接对象快吗?"
    --
    没错,你这样是比较快,但是你还是没有听懂我的意思相对对于数据库连接和SqlConnection对象这两个资源来说,创建前者所耗的资源完全可以让创建SqlConnection对象的资源忽略不记,有时候写代码不是说每个地方都要保证最快,而是要从整体的设计角度来考虑。如果整个应用程序用一个连接实例的话,对于C/S的程序还勉强说的过去,但是对于Web程序来说是绝对的Bad Idea,每次都创建Connection对象浪费的时间比多个线程等待连接的时间相比完全可以不考虑。实际上正是由于SqlClient和OleDb的连接池服务是隐式创建的,所以很多人不注意这个问题,以为保存一个Connection实例可以节省系统资源,但这样做恰恰是让应用程序掉入另一个瓶颈之中。CSDN上对于这个问题已经探讨了很久,我也回答了很多朋友类似的问题,希望你去查找这方面的贴子。
    另外,MSDN中连接池的说明:
    OleDB:
    ms-help://MS.VSCC/MS.MSDNVS.2052/cpguide/html/cpconconnectionpoolingforoledbnetdataprovider.htmSql Client:
    ms-help://MS.VSCC/MS.MSDNVS.2052/cpguide/html/cpconconnectionpoolingforsqlservernetdataprovider.htm另外,提醒一句,保证只有一个连接,不一定是好提议
    你的程序保证一个连接,但是在程序运行期间,这个连接始终被占用,其他程序要访问数据库只有另外创建连接。如果每次都创建的话,由于连接池的应用,连接只在第一次被创建,那么创建的消耗和你的一样,只是多了创建Connection对象的时间,实际上这个对象创建根本不会花费太多的消耗;但是只是每次访问的时候使用了数据库连接,用完之后就回到了连接池,连接空闲的时间就可以被其他应用程序或者其他线程来使用。
      

  17.   

    timmy3310(tim) 都急了 :)
    不过,他说的是对的。
    为什么,要对数据连接使用singeton 模式呢
    完全不应该。
      

  18.   

    web是多线程的
    你的singeton 连接将是一个大问题
      

  19.   

    I don't know how to do:(