我有一个函数,我向SQL Server数据库发送两个请求;但是,在第二个请求中,我得到了SqlException
,并且缺少参数@mpe
。如果我尝试在0
的构造函数中设置常量值SqlParameter
。
protected static string GetX(int mpe, string xsection, string xkey)
{
var xSetup = App.Current.Db.GetType<Data.CachedTypes.XSetup>(
"where mpehotel=@mpe and xsection=@xsection and xkey=@xkey",
new System.Data.SqlClient.SqlParameter("@mpe", mpe),
new System.Data.SqlClient.SqlParameter("@xsection", xsection),
new System.Data.SqlClient.SqlParameter("@xkey", xkey));
if (mpe > 0 && xSetup == null)
{
// Fallback mechanism. Always tries to get the default for all MPEs.
xSetup = App.Current.Db.GetType<Data.CachedTypes.XSetup>(
"where mpehotel=@mpe and xsection=@xsection and xkey=@xkey",
new System.Data.SqlClient.SqlParameter("@mpe", 0), <-- THIS FAILES!!
new System.Data.SqlClient.SqlParameter("@xsection", xsection),
new System.Data.SqlClient.SqlParameter("@xkey", xkey));
但是,如果我将常量值0
提取到本地值int xmpe = 0
并将其传递给构造函数,则SQL查询将按预期执行并检索结果。有人可以解释为什么会这样吗?
答案 0 :(得分:4)
那是因为当你这样做时:
new System.Data.SqlClient.SqlParameter("@mpe", 0)
使用以下构造函数:
public SqlParameter(string parameterName, SqlDbType dbType)
相当于:
new System.Data.SqlClient.SqlParameter("@mpe", SqlDbType.BigInt);
那是因为0可以隐式转换为任何枚举类型,所以这个重载优先于这个:
public SqlParameter(string parameterName, object value)
但是当你这样做时
int someInt = 0; // or anything else
new System.Data.SqlClient.SqlParameter("@mpe", someInt)
任意int不能隐式转换为枚举(只有常数0),因此选择正确的重载(使用object value
)。任意int也可以为0的事实并不重要,因为重载解析是在编译时执行的。但是,如果你这样做:
const int mpe = 0;
new System.Data.SqlClient.SqlParameter("@mpe", mpe);
然后又选择了错误的构造函数,因为在编译时mpe
已知为0。如果你这样做:
const int mpe = 1;
new System.Data.SqlClient.SqlParameter("@mpe", mpe);
由于上述原因,再次选择object value
。
要始终强制正确过载,请将0转换为对象:
new System.Data.SqlClient.SqlParameter("@mpe", (object) 0);