我把程序中使用普遍的代码贴出来,大家看一下,看是否有内存泄漏等占资源的地方,感谢大家!!!//sqlhelper.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace XApp.Data.DBUtility
{
    public abstract class SqlHelper
    {
        public static readonly string connectionString = "server=.;database=XApp;user id=XXX;password=abcdefghijkl;Max Pool Size = 512;";        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandTimeout = 180;
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                int val = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return val;
            }
        }        public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandTimeout = 180;
            SqlConnection conn = new SqlConnection(connectionString);            try
            {
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                cmd.Parameters.Clear();
                return rdr;
            }
            catch
            {
                conn.Close();
                throw;
            }
        }
        private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
        {
            if (conn.State != ConnectionState.Open)
                conn.Open();
            cmd.Connection = conn;
            cmd.CommandText = cmdText;            cmd.CommandType = cmdType;            if (cmdParms != null)
            {
                foreach (SqlParameter parm in cmdParms)
                    cmd.Parameters.Add(parm);
            }
        }
    }
}我所有的数据表都按以下形式做了仿petshop的数据层方式
比如表Conten的数据层设计如下using System;
namespace XApp.Data.Model
{
    [Serializable]
    public class ContenInfo
    {
        public ContenInfo() { }
        public ContenInfo(int ncid,...) 
        {
            this._ncid = ncid;
      ...
        }
        #region Model
        private int _ncid;
  ...
        /// <summary>
        /// ncid
        /// </summary>
        public int ncid
        {
            set { _ncid = value; }
            get { return _ncid; }
        }
...
        #endregion Model
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using XApp.Data.Model;namespace XApp.Data.IDAL
{
    public interface IConten
    {
        IList<ContenInfo> GetCategories(string sqlstr, int pcur, int psize);
        ContenInfo GetCategory(int categoryId);
        void AddCategory(string nctitle,...);
        void UpdateCategory(int ncid, ...);
        void DeleteCategory(int categoryId);
        int Exists(string nctitle);
    }
}using System;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using XApp.Data.Model;
using XApp.Data.IDAL;
using XApp.Data.DBUtility;namespace XApp.Data.SQLServerDAL
{
    public class Conten:IConten
    {
        #region IConten        public void AddCategory(string nctitle, ...)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("insert into Conten(");
            strSql.Append("nctitle,...)");
            strSql.Append(" values (");
            strSql.Append("@nctitle,...)");            SqlParameter[] parameters = {
new SqlParameter("@nctitle", SqlDbType.NVarChar,30),
...};
            parameters[0].Value = nctitle;
    ...
            SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, CommandType.Text, strSql.ToString(), parameters);
        }        public void DeleteCategory(int categoryId)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("delete from Conten ");
            strSql.Append(" where ncid=@ncid ");
            SqlParameter[] parameters = {
new SqlParameter("@ncid", SqlDbType.Int,4)};
            parameters[0].Value = categoryId;
            SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, CommandType.Text, strSql.ToString(), parameters);
        }        public IList<ContenInfo> GetCategories(string sqlstr, int pcur, int psize)
        {
            IList<ContenInfo> categories = new List<ContenInfo>();
            SqlParameter[] parms = new SqlParameter[]{
                new SqlParameter("@sql",SqlDbType.VarChar,1000),
                new SqlParameter("@PageCurrent", SqlDbType.Int,4),
                new SqlParameter("@PageSize", SqlDbType.Int,4),
                new SqlParameter("@PageCount", SqlDbType.Int,4)
            };
            parms[0].Value = sqlstr;
            parms[1].Value = pcur;
            parms[2].Value = psize;
            parms[3].Direction = ParameterDirection.Output;            using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.connectionString, CommandType.StoredProcedure, "sp_PageView", parms))
            {
                rdr.NextResult();
                while (rdr.Read())
                {
                    ContenInfo cat = new ContenInfo(Convert.ToInt32(rdr.GetValue(0)), rdr.GetString(1), rdr.GetString(2),Convert.ToDateTime(rdr.GetValue(3)), ...);
                    categories.Add(cat);
                }
            }
            return categories;
        }        public ContenInfo GetCategory(int categoryId)
        {
            ContenInfo category = new ContenInfo();
            SqlParameter[] parms = new SqlParameter[]{
                new SqlParameter("@cid",SqlDbType.Int,4)
            };
            parms[0].Value = categoryId;            string sql = "SELECT [ncid],... FROM [Conten] WHERE ncid=@cid";
            using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.connectionString, CommandType.Text, sql, parms))
            {
                if (rdr.Read())
                {
                    category = new ContenInfo(Convert.ToInt32(rdr.GetValue(0)), ...);
                }
            }
            
            return category;
        }        public void UpdateCategory(int ncid, ...)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("update Conten set ");
    ...
            SqlParameter[] parameters = {
new SqlParameter("@ncid", SqlDbType.Int,4),
...};
            parameters[0].Value = ncid;
    ...
            SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, CommandType.Text, strSql.ToString(), parameters);
        }        public int Exists(string nctitle)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("select count(1) from Conten");
            strSql.Append(" where nctitle=@nctitle ");
            SqlParameter[] parameters = {
new SqlParameter("@nctitle", SqlDbType.NVarChar,30)};
            parameters[0].Value = nctitle;
            return Convert.ToInt32(SqlHelper.ExecuteScalar(SqlHelper.connectionString, CommandType.Text, strSql.ToString(), parameters)); 
        }
        #endregion
    }
}UI层如下using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using XApp.Command;
namespace XApp.Web.UI
{
    public class View : System.Web.UI.Page
    {
        public View()
        {
            string type = UtilsRequest.GetQueryString("t");
            int id = UtilsRequest.GetQueryStringToInt("id");
            switch (type)
            {
                case "News":
                    HttpContext.Current.Response.Write(Model.ResponseHtml(id));
                    break;
...
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Xml;
using XApp.Data.XML;
using XApp.Data.DBUtility;
using XApp.Data.Model;
using XApp.Data.IDAL;
using XApp.Data.SQLServerDAL;
using XApp.Command;
using System.Web;
namespace XApp.Web.UI
{
    public class Model
    {
        public static string ResponseHtml(int newsid)
        {
            ContenInfo newsinfo = Controller.ContenGet(newsid);
    StringBuilder oHtml = new StringBuilder();
    oHtml.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\"><head>");
            oHtml.Append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\" />");
            oHtml.Append("<title>" + newsinfo.ntitle + "</title>");     
    oHtml.Append("...");
    return oHtml.ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using XApp.Data.Model;
using XApp.Data.IDAL;
using XApp.Data.SQLServerDAL;
namespace XApp.Web.UI
{
    public class Controller
    {
        public static ContenInfo ContenGet(int newsid)
        {
            IConten dal = new Conten();
            return dal.GetCategory(newsid);
        }
    }
}以上即我的网站大体程序架构,请朋友给看看,看是否有内存泄漏等占资源的地方,如何改进,请大家帮忙指正!!!

解决方案 »

  1.   

    ExecuteReader中,Catch中关闭Connection是不够的,要在finally中关闭
    catch(Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    command.Connection.Close();
                    command.Dispose();
                    command = null;
                }
      

  2.   

    如果用了ado.net取数据,就用 try{} finaly {}
      

  3.   

    asp.net+sql2000+win2003sp2架的服务器sql2000占内存从100M-800M并且不减,w3wp是100M-700M,有时w3wp能稍有回落,有时由于超出iis设置自动回收,还有时出现iis假死现象,浏览网页时出现
      

  4.   

    应该还好。
    楼上说的不错。
    Connection即使你关闭了,.net还会保存这个连接以备用。
    .net垃圾收集还是不错的。垃圾收集对象图应该可以遍列,你所有的对象,在合适的时候会帮你清理的。
      

  5.   

    楼上朋友的意思是说我的程序目前看就是没有关闭好数据库连接是吗?这样就会让sql2000以及w3wp都不断的吃内存是吗?
      

  6.   

    cmd.ExecuteReader(CommandBehavior.CloseConnection);
    你这里用了这句 , 那么在你的数据层的时候用完SqlDataReader , 关闭DataReader的时候会自动关闭Connect了。 。。
      

  7.   

    用.NET开发,
    资源占用问题,
    一般更多的来自架构设计和低级的编程思想,
    未显式释放内存造成的问题并不多.
      

  8.   

    相反,我很讨厌在代码里面大量写try{}catch{}finaly{},
    因为这个本身就是个极占资源的东西,
    只适合初学者和小程序.
      

  9.   

    另外我还很频繁的用以下类,来读取缓存中的数据using System;
    using System.Collections;
    using System.Web;
    using System.Web.Caching;
    using System.Collections.Generic;
    using System.Xml;
    namespace XApp.Proxy.Cache
    {    public class Helpers
        {
            #region 
            /// <summary>
            /// 缓存xml文件 Cache
            /// </summary>
            /// <param name="XmlPath">文件路径</param>
            /// <param name="XmlConfName">文件名</param>
            /// <returns>xml内容</returns>
            public static XmlDocument GetXmlCache(string XmlPath,string XmlConfName)
            {
                string CacheName = "XmlConf_" + XmlConfName;
                XmlDocument configDoc = new XmlDocument();
                System.Web.Caching.Cache cache = HttpRuntime.Cache;            if (cache[CacheName] == null)
                {
                    string ConfigPath = null;                #region 取应用程序根物理路径
                    try
                    {
                        ConfigPath = HttpRuntime.AppDomainAppPath;
                    }
                    catch (System.ArgumentException ex)
                    {
                        HttpContext.Current.Response.Write(ex.ToString());
                    }                if (ConfigPath == null) throw new Exception("系统异常,取不到应用程序所在根物理路径!");
                    #endregion                string ConfigFile = ConfigPath + XmlPath + XmlConfName + ".xml";
                    configDoc.Load(ConfigFile);
                    cache.Insert(CacheName, configDoc, new CacheDependency(ConfigFile));
                }
                else
                {
                    configDoc = (XmlDocument)cache[CacheName];
                }            return configDoc;
            }
            #endregion
        }
    }//很频繁用到的网址重写类using System;
    using System.Web;
    using System.Xml;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Collections.Generic;
    using System.Collections;
    using System.Web.Caching;
    namespace XApp.Proxy.UrlRewrite
    {
        public class RewriteModule : IHttpModule
        {
            #region /*RewriteModule 成员*/
            public void Init(HttpApplication application)
            {
                application.BeginRequest += new EventHandler(this.Application_BeginRequest);
            }
            private void Application_BeginRequest(Object obj, EventArgs e)
            {
                HttpApplication app_begin = (HttpApplication)obj;
                HttpContext context = app_begin.Context;
                HttpResponse response = context.Response;
                HttpRequest request = context.Request;
                
                #region /*安全设置*/
                HttpServerUtility Server = app_begin.Server;
                ///************************************************************
                /// Description:修补黑客可能采用".."的方法进入其他目录的问题
                ///************************************************************
                string strURL = Server.UrlDecode(request.RawUrl);
                if (strURL.IndexOf("..") != -1) { throw new HttpException(404, "Not Found"); }
                ///**********************************************************************************
                /// Description:修补"规范化"问题 see: http://support.microsoft.com/?kbid=887459
                ///***********************************************************************************
                if (request.Path.IndexOf('\\') >= 0 || System.IO.Path.GetFullPath(request.PhysicalPath) != request.PhysicalPath) { throw new HttpException(404, "not found"); }
                #endregion            if (IsStaticFile(app_begin.Request.RawUrl.ToLower()))
                {
                
                    #region /*从配置表中找到对应的重写网址*/
                    string oldUrl = app_begin.Request.RawUrl.ToLower();
                    string pattern, come_urlhost, replace, newUrl;
                    XmlDocument configDoc = XApp.Proxy.Cache.Helpers.GetXmlCache("conf//","urlwrite");//有缓存读缓存,否则读xml文件                if (app_begin.Context.Request.Url.Host.ToLower() == "xapp.com"){ app_begin.Context.Response.Redirect("http://www.xapp.com");}
                    else
                    {
                        foreach (XmlElement tmpElement in configDoc.GetElementsByTagName("Rule"))
                        {
                            pattern = tmpElement.GetElementsByTagName("LookFor")[0].FirstChild.InnerText; 
                            come_urlhost = tmpElement.GetElementsByTagName("LookFor")[0].Attributes["UrlHost"].InnerText.ToLower();
                            replace = tmpElement.GetElementsByTagName("SendTo")[0].FirstChild.InnerText;//等同于tmpElement.ChildNodes[1].InnerText;
                            if ((Regex.IsMatch(oldUrl, pattern, RegexOptions.IgnoreCase)) && (come_urlhost == app_begin.Context.Request.Url.Host.ToLower()))
                            {
                                newUrl = Regex.Replace(oldUrl, pattern, replace, RegexOptions.IgnoreCase);//newUrl = Regex.Replace(oldUrl, pattern, replace, RegexOptions.IgnoreCase | RegexOptions.Compiled);
                                context.RewritePath(newUrl);
                                break;
                            }
                        }
                    }
                    #endregion            }        }        public string Right(string sSource, int iLength)
            {
                return sSource.Substring(iLength > sSource.Length ? 0 : sSource.Length - iLength);
            }
            /// <summary>
            /// 不对指定的静态文件做重写匹配
            /// </summary>
            /// <param name="uri"></param>
            /// <returns></returns>
            private bool IsStaticFile(string uri)
            {
                bool s = true;
                string[] sfileArray={"jpg","png","swf","css","js","htm","xml","gif","ico"};
                for (int i = 0; i < sfileArray.Length; i++) { if (Right(uri, 4) == ("." + sfileArray[i])) { s = false; break; } }
                return s;
            }        public void Dispose() { }        #endregion
        }
    }以下为通过XApp.Proxy.Cache类方法缓存的xml文件,内存为网址重写规则表,该文件为12K<?xml version="1.0" encoding="utf-8" ?>
    <Rules>
      <Rule>
        <LookFor UrlHost="www.xapp.com">\/news\/(\d{1,2})\.html</LookFor>
        <SendTo>~/xxx/news.aspx?cid=$1</SendTo>
      </Rule>
      <Rule>
        <LookFor UrlHost="www.xapp.com">\/news\/(\d{1,2})-p(\d{1,2})\.html</LookFor>
        <SendTo><![CDATA[~/xxx/news.aspx?pid=$1&pc=$2]]></SendTo>
      </Rule>
      ....
    </Rules>
    不知道是不是这个东东占的内存?
      

  10.   

    GetXmlCache()里面
    XmlDocument configDoc = new XmlDocument();
    改成
    XmlDocument configDoc = null;然后再
    configDoc = new XmlDocument();
    configDoc.Load(ConfigFile);这样是否要好点?
    类似的问题估计很多,
    没仔细看
      

  11.   


    //sqlhelper.cs
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    using System.Configuration;
    namespace XApp.Data.DBUtility
    {
        public abstract class SqlHelper
        {
            public static readonly string connectionString = "server=.;database=XApp;user id=XXX;password=abcdefghijkl;Max Pool Size = 512;";        public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
            {
                SqlCommand cmd = new SqlCommand();
                cmd.CommandTimeout = 180;
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                    int val = cmd.ExecuteNonQuery();
                    cmd.Parameters.Clear();
                    return val;
                }
            }        public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
            {
                SqlCommand cmd = new SqlCommand();
                cmd.CommandTimeout = 180;
                SqlConnection conn = new SqlConnection(connectionString);            try
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                    SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    cmd.Parameters.Clear();
                    return rdr;
                }
                catch
                {
                    conn.Close();
                    throw;
                }
            }
            private static void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
            {
                if (conn.State != ConnectionState.Open)
                    conn.Open();
                cmd.Connection = conn;
                cmd.CommandText = cmdText;            cmd.CommandType = cmdType;            if (cmdParms != null)
                {
                    foreach (SqlParameter parm in cmdParms)
                        cmd.Parameters.Add(parm);
                }
            }
        }
    }我以上的代码中的public static SqlDataReader ExecuteReader(...)要是改成如下的话        public static SqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
            {
                SqlCommand cmd = new SqlCommand();
                cmd.CommandTimeout = 180;
                SqlConnection conn = new SqlConnection(connectionString);            try
                {
                    PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters
                    SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    cmd.Parameters.Clear();
                    return rdr;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    conn.Close();
                    cmd.Dispose();
                    cmd = null;
                }
            }就提示以下错误
    “/”应用程序中的服务器错误。
    --------------------------------------------------------------------------------阅读器关闭时尝试调用 Read 无效。 
    说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.InvalidOperationException: 阅读器关闭时尝试调用 Read 无效。
      

  12.   

    先做好测试工作如WAS压力测试
    返回reder删除finally
                {
                    conn.Close();
                    cmd.Dispose();
                    cmd = null;
                }
      

  13.   

    using(cmd=new sqlcmd)
    {}
    这个也可以释放一下,再就是异常处理是一款成熟软件必须要做的,一定要写
      

  14.   


    我正在研究压力测试的问题,但我用了finally{conn.Close();...}后报错呀?有点搞不懂了!
      

  15.   

    推荐楼主看下Effective C# 中文版(改善程序的50种方法)
     里面有楼主需要的内容。网上有电子版
      

  16.   

    你的代码挺好的,基本上没有太大问题,就是缺少异常的地方也使用了 using没有什么太大问题,也不是一定就要使用设计模式写出来的就好。唯一就是没有很好的事物处理,可能你的项目都是单表操作.一般 需要事物处理的项目会同一个 getConnection 的方法
      

  17.   

    我是班都是一个表一个表的操作,要不就是视图,不用事物处理!
    但目前就是sql2000占内存比较高,而且久高不下
    另外有个情况:
        1.我是刚换的服务器,原来服务器配置是win2003sp1+sql2000,内存3G,双枋cpu,raid1
        2.现换的服务器是win2003sp2+sql2000,内存6G,四枋cpu,raid1+0
        我的程序在原来服务器运行时基本不用重启,也没有过什么问题,但新换服务器后就得一天左右一重启,不然就不行?这是因为什么原因呢?
      

  18.   

    我的sql2000老机器 数据库=>属性=>选项=>中的“故障还原”模型:设置的是“完全”
                新机器 数据库=>属性=>选项=>中的“故障还原”模型:设置的是“简单”
    这个有影响吗?
    w3wp一班在服务器流量不高时慢慢的占内存会越来越少老服务器iis 内存回收:最大虚拟内存:1000  ,最大使用内存:1000,其它没改
    新服务器iis 内存回收:最大虚拟内存:2000  ,最大使用内存:1500,启用了CPU监视:最大CPU使用率:60%,刷新CPU使用率:5,启动时间限制:10,关闭时间限制:10朋友们看看有何不妥的地方!!!
      

  19.   


    <%@ Page Inherits="XApp.Web.UI.View,XbApp.Web.UI" ValidateRequest="false"  EnableViewState="false" %>我的程序基本都是这个形式,这样会有缓存吗?