SqlParameter(string, object) 无法处理常量值

SqlParameter(string, object) can't handle constant value

我得到了一个函数,可以向 SQL 服务器数据库发送两个请求;然而,在第二个请求中,我得到一个 SqlException 并且缺少参数 @mpe 。如果我尝试在 SqlParameter.

的构造函数中设置常量值 0
    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 查询将按预期执行并检索结果。有人可以解释为什么会这样吗?

那是因为当你这样做时:

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);