【问题标题】:INSERT stored procedure not accepting null valueINSERT 存储过程不接受空值
【发布时间】:2013-10-07 19:23:09
【问题描述】:

我已经从一个 SELECT 存储过程中执行了一个 SqlDataReader,并且我持有这些值,其中一些可能是空的……我不知道。我正在尝试将这些值传递到 INSERT 存储过程的参数中。

当我尝试传递值时收到此错误:

"过程或函数 'insbuRenewal' 需要参数 '@TransactionID',未提供"

我的代码:

try
{
    while (reader.Read())
    {
        insbuRenewal.Parameters["@SolarID"].Value = (decimal)reader["SolarID"];
        insbuRenewal.Parameters["@ApplicationID"].Value
            = reader["ApplicationID"].ToDecimalOrNull();
        insbuRenewal.Parameters["@TransactionID"].Value
            = reader["TransactionID"].ToStringOrNull();
        insbuRenewal.Parameters["@Host"].Value
            = reader["Host"].ToStringOrNull();

    public static string ToStringOrNull(this object items)
    {
        if (items == null || items == DBNull.Value)
        {
            return null;
        }
        return items.ToString(); 
    }

【问题讨论】:

  • 因为你试图在c#中插入null,这里需要插入DBNull.Value
  • 如果你也包含存储过程会很有帮助
  • 我相信要做到这一点,存储过程中的参数必须有一个默认值。您是否有权查看代码?见weblogs.asp.net/rmclaws/archive/2004/02/18/75381.aspx
  • 您真的需要.ToStringOrNull() 函数吗?如果 reader["ApplicationID"] 的值已经是 DbNull.Value,那么它将被传递。
  • 代码不完整。您在哪里调用 ExecuteNonQuery?你在哪里定义参数?请出示完整的相关代码

标签: c# .net ado.net


【解决方案1】:

如果你这样做,你可以使用你拥有的方法:

insbuRenewal.Parameters.AddWithValue("@TransactionID",
    reader["TransactionID"].ToStringOrNull());

代替:

insbuRenewal.Parameters["@TransactionID"].Value =
    reader["TransactionID"].ToStringOrNull();

AddWithValue 接口对于您的所有参数来说是一种更好的方法。不要预先添加它们;按需添加。


正如 Yosi 指出的那样。您真正需要的是:

insbuRenewal.Parameters.AddWithValue("@TransactionID", reader["TransactionID"]);

【讨论】:

  • 即使使用AddWithValue,如果值为null,您仍然需要使用DBNull.Value。看我的回答。
  • @gunr2171,这不是真的。我有数百行代码将null 发送到AddWithValue 方法,并且数据库按预期更新。此外,它在SELECT 语句中按预期工作。
  • @gunr2171,答案说明了什么并不重要。我做。它有效。
  • 为什么要转换一个值(到字符串),当你知道以后,它会再次转换为另一个值(到 int)
  • @gunr2171,我知道了。有很多人认为他们需要这样做。但是很多人仍然认为他们不需要将using 语句与所有ADO.NET 对象一起使用。仅仅因为您可以找到 1,000 个错误或不必要的代码示例,这是否使它们正确?
【解决方案2】:

要扩展@neoistheone 的答案,如果您的值为空,您还需要传入DBNull.Value

采取这种扩展方法:

public static void AddParameter(this SqlCommand cmd, string name, object value)
{
    if (value == null)
        cmd.Parameters.AddWithValue(name, DBNull.Value);
    else
        cmd.Parameters.AddWithValue(name, value);
}

现在这样称呼它:

insbuRenewal.AddParam("@ApplicationID", 
    reader["ApplicationID"].ToDecimalOrNull());

【讨论】:

  • 不需要为此创建方法,为什么在添加参数时不指定类型?
  • @Yosi,我专门使用这种方法来添加参数。我不必担心转换类型,如果值为 null,它会为我处理。
  • 这完全是多余的,你得到了什么额外的功能?
  • @Yosi,否则你为什么要做一个函数?为了减少你必须编写代码的次数!通过使用这个函数每次我添加一个参数,我节省了大量时间a)不检查它是否为空,b)不关心转换数据类型。另外,您的解决方案不考虑空值。
  • 当然,创建函数的主要目的之一是重用。但是,这里不需要创建函数!这里的选角是为您提供的。
【解决方案3】:

您应该使用DBNull 而不是null。一般来说,您需要将对象转换为数据库类型,这样null 将自动转换为DBNull

你真的不需要自己做演员。

添加每个参数时需要指定数据库类型:

insbuRenewal.Parameters.Add(
    "@TransactionID", SqlDbType.VarChar, 256).Value = "somestring..";

【讨论】:

  • 通过在添加参数时指定值SqlDbType.VarChar,将从您分配给它的string 值进行转换。
猜你喜欢
  • 2019-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多