zoukankan      html  css  js  c++  java
  • .Text中的Bug

      今天下午三点左右,打开博客园的文章时,出现了这样的错误:“The SqlParameter with ParameterName '@EntryID' is already contained by another SqlParameterCollection”。我重启了IIS,临时消除了故障。
      我仔细查看了.Text中的代码,发现了两处问题:
    1、打开一篇文章时,.Text中调用的是blog_GetEntryByID存储过程,而在创建存储过程的参数时,用的是这样的代码:
    SqlParameter[] p =
        {
         SqlHelper.MakeInParam("@EntryID",SqlDbType.Int,0,EntryID)
        };
    一般情况下, 0应该改成4,一开始怀疑是这个原因造成上述故障的。但查了一下MSDN, 在SqlParameter的帮助中有这样的一句话:“如果未在 size 参数中显式设置 Size,则可根据 dbType 参数的值推断出该大小。”。即使设成0, 系统也会自动推断出SqlDbType.Int的大小。实际上,如果上面的代码有问题,.Text根本就无法正常使用。所以这个问题不是一个问题。
    2、第二问题是在google上查找到的,我找到了这样的文章:http://www.dotnetforums.com/showthread.php?t=244。文章中有这样的代码:
    try {
    return cmd.ExecuteReader(CommandBehavior.CloseConnection);

    }catch(SqlException sqle){
    //if stp FAILS and we don't clear command collection,
    //the next request will throw: "The SqlParameter with ParameterName
    //'XXXX' is already contained by another SqlParameterCollection" error

    cmd.Parameters.Clear();

    cmd.Dispose();
    if (conn.State == ConnectionState.Open) {
    conn.Close();
    }
    代码的注释中讲得很明白,如果在cmd.ExecuteReader时产生异常,而没有调用cmd.Parameters.Clear();就会发生博客园今天出现的故障。
    再看一下,.Text中的相关代码:

    private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)

             {   

                 

                  //create a command and prepare it for execution

                  SqlCommand cmd = new SqlCommand();

                  PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters);

                 

                  //create a reader

                  SqlDataReader dr;

     

                  // call ExecuteReader with the appropriate CommandBehavior

                  if (connectionOwnership == SqlConnectionOwnership.External)

                  {

                       dr = cmd.ExecuteReader();

                  }

                  else

                  {

                       dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                  }

                 

                  // detach the SqlParameters from the command object, so they can be used again.

                  cmd.Parameters.Clear();

                 

                  return dr;

             }

    其中的cmd.Parameters.Clear();表明作者已经考虑到了这个问题,但却忘了考虑异常情况, 应该是在finally中执行cmd.Parameters.Clear(); 正确的代码如下:

    private static SqlDataReader ExecuteReader(SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, SqlConnectionOwnership connectionOwnership)

             {   

                  //create a command and prepare it for execution

                  SqlCommand cmd = new SqlCommand();

                  //create a reader

                  SqlDataReader dr;

                  try

                  {

                       PrepareCommand(cmd, connection, transaction, commandType, commandText, commandParameters);

                 

                       // call ExecuteReader with the appropriate CommandBehavior

                       if (connectionOwnership == SqlConnectionOwnership.External)

                       {

                           dr = cmd.ExecuteReader();

                       }

                       else

                       {

                           dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                       }

                  }

                  finally

                  {

                       // detach the SqlParameters from the command object, so they can be used again.

                       cmd.Parameters.Clear();

                  }

                  return dr;

             }

      
    BTW:
      如何更好地捕捉.Text产生的异常?我觉得仅仅是在产生异常时抛出异常并在Web页面显示是不够的。因为管理员无法知道其他人使用时产生的异常。所以在Web页面显示异常的同时,应该把异常写入日志。在.Text中,有一个方便、简单的方法,就是在Error.aspx.cs中加上Dottext.Framework.Logger.LogManager.Log("Error",exceptionMsgs.ToString());

  • 相关阅读:
    apache配置虚拟主机的三种方式
    mysql ddl语句
    MySQL锁机制
    如何卸载rpm包
    RAC SCAN
    oracle rac scan ip 用途 原理
    如何用udev for asm in oracle linux 6
    ORACLE RAC NTP 时间服务器配置
    对表空间 'USERS' 无权限
    bootstrap全局css样式
  • 原文地址:https://www.cnblogs.com/dudu/p/18834.html
Copyright © 2011-2022 走看看