当前位置:首页 --> 错误日志 --> 正文

当前命令发生了严重错误。应放弃任何可能产生的结果

2008-6-15 22:49:00 来源: 浏览次数: 评论数: 字号:[ ]

今天项目出现了如下的错误:

REPORT:

“/”应用程序中的服务器错误。


当前命令发生了严重错误。应放弃任何可能产生的结果。
当前命令发生了严重错误。应放弃任何可能产生的结果。

说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.Data.SqlClient.SqlException: 当前命令发生了严重错误。应放弃任何可能产生的结果。
当前命令发生了严重错误。应放弃任何可能产生的结果。

源错误:

 

232:            {

233:                ErrorLog.WriteLog(Ex);

234:                        throw Ex;

235:            }

236:            if (_AutoClose)


源文件: D:\CVSPROJ\XXXXX\DataProvider\SqlDBO.cs    : 234

堆栈跟踪:

 

[SqlException (0x80131904): 当前命令发生了严重错误。应放弃任何可能产生的结果。

当前命令发生了严重错误。应放弃任何可能产生的结果。]

   RM.DataProvider.SqlDBO.ExecuteNonQuery(String ExSql, SqlCmdParam[] MyCmdParam) in D:\CVSPROJ\XXXXX\DataProvider\SqlDBO.cs:234

   RM.Basic.DALBase.Add(Hashtable hTable) in D:\CVSPROJ\XXXXX\Basic\DALBase.cs:61

   RM.BLL.RM_Web_Article.Add(RM_Web_Article MyEntity) in D:\CVSPROJ\XXXXX\BLL\RM_Web_Article.cs:28

   RM.WebApp.Admin.Admin_Article.btn_Save_Click(Object sender, EventArgs e) in D:\CVSPROJ\XXXXX\WebApp\Admin\Admin_Article.aspx.cs:197

   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105

   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +107

   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7

   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11

   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33

   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102

 


版本信息: Microsoft .NET Framework 版本:2.0.50727.42; ASP.NET 版本:2.0.50727.210

 

 

出现问题的对应表DDL是:

CODE:

CREATE TABLE [dbo].[RM_Web_Info] (

    [fdID] [int] IDENTITY (1, 1) NOT NULL ,

    [fdClassID] [int] NOT NULL ,

    [fdTitle] [varchar] (100) COLLATE Chinese_PRC_CI_AS NOT NULL ,

    [fdContent] [text] COLLATE Chinese_PRC_CI_AS NOT NULL ,

    [fdCreateTime] [smalldatetime] NOT NULL ,

    [fdModifyTime] [smalldatetime] NOT NULL

)

问题却是出现在text类型的fdContent字段上。

 

google+baidu有一种原因是:SQL Server打了SP4后出现的,建议卸裁SP4。但由于win2k3+SQL Server如果没有打SP4的话,是会有安全风险的,所以这个解决方案没有使用。

 

仔细检查代码后发现,操作数据库时,通过下面的代码构造SQL和相应的命令:

CODE:

string strSql = "INSERT INTO {0}({1})VALUES({2});";

string strField = "";

string strVal = "";

int i = 0;

SqlDBO.SqlCmdParam[] MyParam = new SqlDBO.SqlCmdParam[hTable.Count];            

foreach (DictionaryEntry dict in hTable)

{

    int idx = Array.IndexOf(strFields, dict.Key.ToString());

    if (idx != -1)

    {

        MyParam[i] = MyDBO.CreateNewParam(string.Format("@{0}", strFields[idx]), SqlDBO.GetDbType(dict.Value), dict.Value);

        if (this.strPKName != dict.Key.ToString())

        {

            strField += string.Format("[{0}]", strFields[idx]) + ",";

            strVal += string.Format("@{0}", strFields[idx]) + ",";

        }

        i++;

    }

}

if (i > 0)

{

    strField = strField.TrimEnd(',');

    strVal = strVal.TrimEnd(',');

    if (i < hTable.Count) MyParam = (SqlDBO.SqlCmdParam[])RM.Common.Method.Redim(MyParam, i);

}

strSql = string.Format(strSql, this.strTableName, strField, strVal);

有一个SqlDBO.GetDbType(Object) 类型的方法,根据变量的类型得到SqlDbType数据。方法由如下方式得到对应的值:

CODE:

Type varType = _Var.GetType();

switch (Type.GetTypeCode(varType))

{

    //这里省掉

    case TypeCode.String:

    default:

        {

            if (_Var.ToString().Length > 8000)

            {

                return SqlDbType.Text;

            }

            else

            {

                return SqlDbType.VarChar;

            }

        }

}

结合上面的代码片断,大致的原因就可以找出来了。

上面的代码得到的SQL命令格式如:

CODE:

exec sp_executesql N'SELECT * FROM RM_Admin_Group WHERE fdID=@fdID;', N'@fdID int', @fdID = 1

也就是,虽然是在构造SQL命令,但是执行时,却是调用的系统存储过程。

这是其一,另外在C#中调用字符串的Length属性,得到的是字符串,与编码无关。当字符串在8000以内时,得到的是SqlDbType.VarChar 类型。这是其二。

两者结合的结果是。在调用sql_excutesql存储过程时,给一个VarChar类型的数据最大传递8000个字符的数据。而VarChar只有ASCII字符集才能存储8000个,否则像UTF-8这样的编码,最大长度只能存放4000个了。

       将上面得到SqlDbType的代码改成如下,则测试通过:

CODE:

Type varType = _Var.GetType();

switch (Type.GetTypeCode(varType))

{

    //这里省掉

    case TypeCode.String:

    default:

        {

            if (_Var.ToString().Length > 4000)

            {

                return SqlDbType.Text;

            }

            else

            {

                return SqlDbType.VarChar;

            }

        }

}

 

后记:任何便利的东西都会有副作用,创建参数时,最好还是根据字段的类型选择SqlDbType的值。

?
?