参数化查询…期望参数“ @units”(未提供)


76

我收到此异常:

参数化查询'(@Name nvarchar(8),@ type nvarchar(8),@ units nvarchar(4000),@ rang'期望使用未提供的参数'@units'。

我的插入代码是:

public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        SqlCommand command = new SqlCommand();
        command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
        command.Connection = connection;
        command.Parameters.AddWithValue("@Name", name);
        command.Parameters.AddWithValue("@type", type);
        command.Parameters.AddWithValue("@units", units);
        command.Parameters.AddWithValue("@range", range);
        command.Parameters.AddWithValue("@scale", scale);
        command.Parameters.AddWithValue("@description", description);
        command.Parameters.AddWithValue("@guid", guid);
        return (int)command.ExecuteScalar();
    }
}

异常令人惊讶,因为我正在使用该AddWithValue函数并确保为该函数添加了默认参数。

解决了:

问题在于一些参数在其中为空字符串(覆盖默认值)

这是工作代码:

public int insertType(string name, string type, string units = "N\\A", string range = "N\\A", string scale = "N\\A", string description = "N\\A", Guid guid = new Guid())
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            SqlCommand command = new SqlCommand();
            command.CommandText = "INSERT INTO Type(name, type, units, range, scale, description, guid) OUTPUT INSERTED.ID VALUES (@Name, @type, @units, @range, @scale, @description, @guid) ";
            command.Connection = connection;
            command.Parameters.AddWithValue("@Name", name);
            command.Parameters.AddWithValue("@type", type);

            if (String.IsNullOrEmpty(units))
            {
                command.Parameters.AddWithValue("@units", DBNull.Value); 
            }
            else
                command.Parameters.AddWithValue("@units", units);
            if (String.IsNullOrEmpty(range))
            {
                command.Parameters.AddWithValue("@range", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@range", range);
            if (String.IsNullOrEmpty(scale))
            {
                command.Parameters.AddWithValue("@scale", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@scale", scale);
            if (String.IsNullOrEmpty(description))
            {
                command.Parameters.AddWithValue("@description", DBNull.Value);
            }
            else
                command.Parameters.AddWithValue("@description", description);




            command.Parameters.AddWithValue("@guid", guid);


            return (int)command.ExecuteScalar();
        }


    }

1
您忘记了将@每个参数名称的第一个字符放在。
安德鲁·莫顿

@AndrewMorton:为什么错误消息抱怨@units而不是@Name,它首先出现?
OR Mapper 2014年

@ORMapper我想它不必按提供的顺序查找它们。
安德鲁·莫顿

我很震惊,因为仍然没有人回答这个问题。顺便说2一下?
SonerGönül2014年

@AndrewMorton我添加了@并且仍然是相同的例外
Yogevnn

Answers:


98

试试这个代码:

SqlParameter unitsParam = command.Parameters.AddWithValue("@units", units);
if (units == null)
{
    unitsParam.Value = DBNull.Value;
}

并且您必须检查所有其他参数是否为空值。如果为null,则必须传递DBNull.Value值。


1
我不认为它可以为null,因为OP具有这样的参数string units = "N\\A"
meda 2014年

3
可以这样,因为您可以调用这样的方法insertType(null, null, null, null, null, null);
Denis

问题解决了!我将使用解决方案来编辑​​我的消息。谢谢你们!
Yogevnn 2014年

@GrantWinney显然这不是它的工作方式。必须从调用代码中省略该参数,而不是将其设置为null命名和可选参数
Andrew Morton 2014年

@GrantWinney默认值不是那样的。它们仅在您不传递任何内容时才适用(如果您完全省略该参数)。如果您根本不传递任何东西,即使null,那么您传递的就是被呼叫者看到的东西。

35

这是使用null-coalescing运算符的一种方法:

cmd.Parameters.AddWithValue("@units", units ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@range", range ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@scale", scale ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value);

或更严格的类型检查:

cmd.Parameters.Add("@units", SqlDbType.Int).Value = units ?? (object)DBNull.Value;
cmd.Parameters.Add("@range", SqlDbType.Int).Value = range ?? (object)DBNull.Value;
cmd.Parameters.Add("@scale", SqlDbType.Int).Value = scale ?? (object)DBNull.Value;
cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = description ?? (object)DBNull.Value;

运营商也被束缚:

int?[] a = { null, null, 1 };
Console.WriteLine(a[0] ?? a[1] ?? a[2]);

3

到目前为止,对于这些问题,扩展类对我很有用:

public static class DbValueExtensions
{
    // Used to convert values coming from the db
    public static T As<T>(this object source)
    {
        return source == null || source == DBNull.Value
            ? default(T)
            : (T)source;
    }

    // Used to convert values going to the db
    public static object AsDbValue(this object source)
    {
        return source ?? DBNull.Value;
    }
}

您通常会在两种情况下使用它。首先,在为查询创建参数时:

var parameters = new Dictionary<string, object>
{
    { "@username", username.AsDbValue() },
    { "@password", password.AsDbValue() },
    { "@birthDate", birthDate.AsDbValue() },
};

或解析SqlReader值时:

while (reader.Read())
{
    yield return new UserInfo(
        reader["username"].As<string>(),
        reader["birthDate"].As<DateTime>(),
        reader["graduationDate"].As<DateTime?>(),
        reader["nickname"].As<string>()
    );
}


0

这是一种可以与多个参数一起重用的方法:

public void NullorEmptyParameter(QC.SqlCommand command, string at, string value)
{
    if (String.IsNullOrEmpty(value))
    {
        command.Parameters.AddWithValue(at, DBNull.Value);
    }
    else
        command.Parameters.AddWithValue(at, value);
}

然后,您可以将其重用于许多命令和参数:

NullorEmptyParameter(command, "@Idea_ID", Idea_ID);
NullorEmptyParameter(command, "@Opportunities_or_Idea", Opportunities_or_Idea);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.