以下代码在本机及服务器上测试均存在相同问题,浏览量少一切正常,当频繁刷新或同时浏览量大时,提示aspx页面上的绑定找不到数据列,System.Web.HttpException: DataBinding:“System.Data.DataRowView”不包含名为“sitename”的属性,得出此类异常信息.操作系统windows server 2003,开发工具 vs 2008,asp.net 2.0, 数据库是mssql 2005.网站中用到了HttpModules做流量统计,在其中使用以下DbHelper类,该helper类使用singleton模式编写,在module中是静态的,目的是希望无论多少请求都只使用一个helper类完成流量的记录,并由于害怕连接过多,所以connection对象在DbHelper类中也是静态的.请看代码:
public class DbHelper : IDisposable
    {
        private static string m_strConn;
        private static DbHelper m_singleton;
        private SqlConnection m_conn;        private DbHelper()
        { }        private DbHelper(string connStr)
        {
            m_strConn = connStr;
            m_conn = new SqlConnection(connStr);
        }        public static DbHelper CreateHelper(string connStr)
        {
            m_strConn = connStr;
            if (m_singleton == null)
                m_singleton = new DbHelper(m_strConn);
            return m_singleton;
        }        public static DbHelper CreateHelper()
        {
            if (m_singleton == null)
                m_singleton = new DbHelper(m_strConn);
            return m_singleton;
        }        public DataTable GetTableBySql(string SqlStatement, SqlParameter[] parameters, CommandType cmdType)
        {
            DataTable dt = new DataTable();
            using (SqlCommand cmd = PrepareCommand(SqlStatement, parameters, cmdType))
            {
                SqlDataAdapter adap = new SqlDataAdapter(cmd);
                try
                {
                    adap.Fill(dt);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    cmd.Parameters.Clear();
                    m_conn.Close();
                }
            }
            return dt;
        }        public DataRow GetRowBySql(string SqlStatement, SqlParameter[] parameters, CommandType cmdType)
        {
            DataRow row = null;
            using (SqlCommand cmd = PrepareCommand(SqlStatement, parameters, cmdType))
            {
                SqlDataAdapter adap = new SqlDataAdapter(cmd);
                DataTable dt = new DataTable();
                try
                {
                    adap.Fill(dt);
                    row = dt.Rows[0];
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    cmd.Parameters.Clear();
                    m_conn.Close();
                }
            }
            return row;
        }        public void ExcuteNonQuery(string SqlStatement, SqlParameter[] parameters, CommandType cmdType)
        {
            using (SqlCommand cmd = PrepareCommand(SqlStatement, parameters, cmdType))
            {
                try
                {
                    m_conn.Open();
                    cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    m_conn.Close();
                }
            }
        }        public int ExcuteScalar(string SqlStatement, SqlParameter[] parameters, CommandType cmdType)
        {
            int ret = 0;
            using (SqlCommand cmd = PrepareCommand(SqlStatement, parameters, cmdType))
            {
                try
                {
                    m_conn.Open();
                    ret = Convert.ToInt32(cmd.ExecuteScalar());
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    cmd.Parameters.Clear();
                    m_conn.Close();
                }
            }
            return ret;
        }        private SqlCommand PrepareCommand(string SqlStatement, SqlParameter[] parameters, CommandType cmdType)
        {
            if (string.IsNullOrEmpty(SqlStatement))
                return null;
            SqlCommand cmd = new SqlCommand(SqlStatement);
            if (parameters != null && parameters.Length > 0)
                cmd.Parameters.AddRange(parameters);
            cmd.CommandType = cmdType;
            cmd.Connection = m_conn;
            return cmd;
        }        #region IDisposable 成员        public void Dispose()
        {
            m_conn.Close();
            m_conn.Dispose();
            GC.SuppressFinalize(true);
        }        #endregion
    }
用法:
public class MyPage : System.Web.UI.Page //站内所有页面都继承此页,页面不多
    {
        private DbHelper helper = DbHelper.CreateHelper(ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString);        protected DbHelper DBHelper
        {
            get { return helper; }
        }        public MyPage()
        {        }
    }

解决方案 »

  1.   

    在线等,自己顶一下,再附上HttpModule的代码
    public class RefererModule : IHttpModule
        {
            private static DbHelper helper = DbHelper.CreateHelper(ConfigurationManager.ConnectionStrings["TestConnectionString"].ConnectionString);        #region IHttpModule 成员        public void Dispose()
            {
                throw new NotImplementedException();
            }        public void Init(HttpApplication context)
            {
                context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
            }        /// <summary>
            /// 进行流量统计,并将合作网站带来的流量作统计
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void context_AcquireRequestState(object sender, EventArgs e)
            {
                //...这里略去使用DbHelper所做的数据操作        }        #endregion
        }
      

  2.   

    打开就关闭就可以了,不要这么复杂。.net有自己的连接池保护。
      

  3.   

    不包含名为“sitename”这句错在。你数据集里没有这个字段。
      

  4.   

    sitename只是其中一个,数据集里实际上所有字段都报找不到
      

  5.   


    public static DataSet ExecuteDataset(string strCon,CommandType cmdType,string cmdText,params SqlParameter[] cmdParms)
    {
    SqlCommand cmd = new SqlCommand();
    using (SqlConnection conn = new SqlConnection(strCon)) 
    {
    PrepareCommand(cmd, conn, null,cmdType, cmdText, cmdParms);
    SqlDataAdapter adp = new SqlDataAdapter();
    DataSet ds = new DataSet();
    adp.SelectCommand = cmd;
    adp.Fill(ds);
    cmd.Parameters.Clear();
    adp.Dispose();
    return ds;
    }
    }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; if (trans != null)
    cmd.Transaction = trans; cmd.CommandType = cmdType; if (cmdParms != null) 
    {
    foreach (SqlParameter parm in cmdParms)
    cmd.Parameters.Add(parm);
    }
    }你写的好纠结啊。Db层不要处理异常吧。应该放在业务层去处理异常吧。
      

  6.   

    首先那个异常信息肯定不是连接池满的意思(除非你的代码隐藏了异常,造成调试困难)。从被调用的代码看不出什么。这需要查看你aspx出错时的堆栈信息,看看哪个数据源设置语句出错。只有列出具体哪一条语句需要绑定有sitename字段的数据集,从这一条语句深入,才能分析跟踪异常。如果是“频繁刷新或同时浏览量大”时才出现异常,大多数是因为滥用了Session、Application、静态变量这类情况,使得原本应该属于一次页面处理局部范围的对象被不恰当地定义为多个线程相互覆盖的作用域的,这通常只要把变量变为private,或者状态放入ViewState就可以解决。
      

  7.   

    看上去,你的aspx中用来保存 SqlStatement 的东东,大概使用了静态变量、Application或者Session保存,才会造成查询结果张冠李戴。
      

  8.   

    非常感谢sp1234,错误的详细情况是,整个站点瘫痪,所有的数据连接都报找不到某某字段的错误,程序中只有一到两个很简单的登录页有使用Session,Application更是一次也没用上,关键应该是多线程的问题,System.Web.UI.Page类中的静态成员变量,在整个生命期中,是不是只是被创建一次?还有HttpModule是每接到一个请求,由asp.net引擎new一次?关于线程与asp.net的作用域及生命期中的静态成员,概念很是模糊,感谢解答
      

  9.   

    SqlStatement在调用方全部是用字符串常量传递的,并没有使用静态变量,但每个页面中的DbHelper引用却是静态的
      

  10.   

    但是既然是aspx页提示绑定时数据不对,你就可以只看眼前出问题的那一个aspx的源代码,看看它查询数据时是怎么提供 SqlStatement 的值的。先找准出问题的具体语句(绑定数据前查询数据库肯定就错了),让后才能找出来谁把它给破坏了。当然了,如果有时间,应该将DBHelper修改为返回(泛型)强类型的对象集合,而不是丢个DataTable、DataRow出来,过度追求弱类型等你出了问题后悔都没有办法(因为程序自己无法准确定位问题)。
      

  11.   


    你的DbHelper每一个方法其实内部都是临时分配局部变量的,例如你的GetTableBySql方法,似乎都是临时分配变量嘛(除了m_conn,但是这个并不改变)。是singleton还是static,还是创建对象,都没有什么区别。
      

  12.   

    其实目的就是让SqlConnection的数量保持在非常低的水平,里面的诸如Command等的都不重要,主要是因为连接数限制太紧了,也不知道这样做能不能有效果,有点头绪了,谢谢sp1234前辈,结贴给分