本文讲述一次 .NET WinForm 程序调试的经过。该程序在业务部门的计算机中运行时出现“SqlDbType 枚举值 31 无效”错误,而在我自己的机器上运行正常。
我用 C# 编写的一个 WinForm 程序,在业务部门的机器上运行出现“SqlDbType 枚举值 31 无效”错误,如下图所示:
而这个程序在我自己的机器上运行很正常:
于是我就到业务部门的机器上打开该程序的 debug 模式(在程序命令行后跟 /debug 参数,下面这个屏幕截图是在我自己的机器上截取的):
再次运行这个程序,得到更详细的错误信息:
可以看出,是 Skyiv.Ben.Icbc.Mis.Mgr.Data 命名空间中的 AccBalance 类的 GetValues 方法在调用 System.Data.SqlClient 命名空间中的 SqlParameter 类的构造函数时出错了。AccBalance 类的 GetValues 方法如下所示:
namespace Skyiv.Ben.Icbc.Mis.Mgr.Data
{
sealed class AccBalance : DbObject
{
public AccBalance(string newConnectionString) : base(newConnectionString) { }
public SqlDataReader GetValues(DateTime dateBegin, DateTime dateEnd)
{
SqlParameter[] p =
{
new SqlParameter("@DateBegin", SqlDbType.Date),
new SqlParameter("@DateEnd", SqlDbType.Date)
};
p[0].Value = dateBegin;
p[1].Value = dateEnd;
return RunReader("prMgr_GetAccBalanceByDateRange", p);
}
}
}
看来 SqlDbType.Date 枚举值就是 31 了。我们写个程序来验证一下:
using System;
using System.Data;
namespace Skyiv.Tester
{
sealed class SqlDbTypeTester
{
static void Main()
{
try
{
Console.WriteLine(" OS Version: " + Environment.OSVersion);
Console.WriteLine("CLR Version: " + Environment.Version);
Console.WriteLine();
ListEnumMembers(typeof(SqlDbType));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void ListEnumMembers(Type type)
{
Console.WriteLine("{0} Members:", type);
foreach (var value in Enum.GetValues(type))
Console.WriteLine("{0,3} {1}", (int)value, value);
}
}
}
在我自己的机器上编译和运行:
果然如此。然后再把这个 SqlDbTypeTester.exe 程序拷贝到业务部门的机器运行一下:
咦,枚举值为 31 的 SqlDbType.Date 不见了。难怪业务部门机器上运行上述 WinForm 程序时会出现“SqlDbType 枚举值 31 无效”错误。我的机器上的 CLR 版本是 2.0.50727.1882,而业务部门机器上的 CLR 版本是 2.0.50727.832,也就是 2.0 RTM 版本。看来这个错误是 .NET CLR 版本太低造成的。在业务部门的机器上安装 .NET Framework 2.0 SP2 后就解决了这个问题。请参见“Microsoft .NET Framework 的版本”。
在 Ubuntu 10.10 操作系统的 mono 2.6.7 环境下编译和运行:
在 Ubuntu 10.10 操作系统的 mono 2.8.1 环境下编译和运行:
在 Ubuntu 10.10 操作系统的 mono 2.6.7 环境的 CLR 1.1 版本中运行: