SqlParameter(String,Object)无法处理常量值

Jen*_*wka 3 c# sql-server sqlparameter

我有一个函数,可以向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));
Run Code Online (Sandbox Code Playgroud)

但是,如果我将常量值提取0为局部值int xmpe = 0并将其传递给构造函数,则SQL查询将按预期执行,并检索结果。有人可以解释为什么会这样吗?

Evk*_*Evk 5

那是因为当您这样做时:

new System.Data.SqlClient.SqlParameter("@mpe", 0)
Run Code Online (Sandbox Code Playgroud)

使用以下构造函数:

public SqlParameter(string parameterName, SqlDbType dbType)
Run Code Online (Sandbox Code Playgroud)

等效于:

new System.Data.SqlClient.SqlParameter("@mpe", SqlDbType.BigInt);
Run Code Online (Sandbox Code Playgroud)

这是因为0可以隐式转换为任何枚举类型,所以此重载比该重载更可取:

public SqlParameter(string parameterName, object value)
Run Code Online (Sandbox Code Playgroud)

但是当你这样做

int someInt = 0; // or anything else
new System.Data.SqlClient.SqlParameter("@mpe", someInt)
Run Code Online (Sandbox Code Playgroud)

任意int不能隐式转换为enum(仅常量0是),因此选择正确的重载(带有object value)。任意int也可以为0的事实无关紧要,因为重载解析是在编译时执行的。但是,如果您这样做:

const int mpe = 0;
new System.Data.SqlClient.SqlParameter("@mpe", mpe);
Run Code Online (Sandbox Code Playgroud)

然后再次选择错误的构造函数,因为mpe在编译时已知为0。如果您这样做:

const int mpe = 1;
new System.Data.SqlClient.SqlParameter("@mpe", mpe);
Run Code Online (Sandbox Code Playgroud)

object value由于上述原因,再次选择。

要始终强制纠正过载,请将0强制转换为对象:

new System.Data.SqlClient.SqlParameter("@mpe", (object) 0);
Run Code Online (Sandbox Code Playgroud)