【问题标题】:Stored procedure doesn't allow null parameters even the parameter represent accept nulls?即使参数表示接受空值,存储过程也不允许空参数?
【发布时间】:2016-08-19 02:44:28
【问题描述】:

我看到很多关于堆栈溢出的问题,没有一个涉及我自己的问题

过程或函数需要未提供的参数

我创建了这个 SQL Server 存储过程:

CREATE proc [dbo].[spAddCustomer]
    @cuName varchar(50),
    @cuAddress varchar(50),
    @cuMobile varchar(50),
    @cuImage image,
    @cityId int,
    @exist int output
AS
BEGIN
    IF NOT EXISTS(SELECT Cu_Mobile FROM tblCustomers WHERE Cu_Mobile = @cuMobile)
    BEGIN
        INSERT INTO tblCustomers (Cu_Name, Cu_Address, Cu_Mobile, Cu_Image, City_ID)
        VALUES (@cuName, @cuAddress, @cuMobile, @cuImage, @cityId)

        SET @exist = 1
    END
    ELSE
        SET @exist = 0
END

在我的数据访问层中,我有这个负责非查询命令的方法:

public static int ExecuteNonQuery(string query, CommandType type, params SqlParameter[] arr)
{
    int outParam;

    SqlCommand cmd = new SqlCommand(query, cn);
    cmd.Parameters.AddRange(arr);
    cmd.CommandType = type;

    int i = cmd.ExecuteNonQuery();

    foreach (SqlParameter param in arr)
    {
        if (param.Direction == ParameterDirection.Output)
        {
            outParam = (int)cmd.Parameters[param.ToString()].Value;
            return outParam;
        }
    }

    return i;
}

负责创建参数的方法:

public static SqlParameter CreateParameter(string name, SqlDbType type, object value, ParameterDirection pd = ParameterDirection.Input)
{
    SqlParameter pr = new SqlParameter();
    pr.ParameterName = name;
    pr.Direction = pd;
    pr.SqlDbType = type;
    pr.SqlValue = value;

    return pr;
}

业务层中的这个方法,从表示层传递参数

public static int spAddCustomer(string cusName, string cusAddress, string cusMobile, byte[] arrImg, int cityId)
{
    DataAccessLayer.Open();

    int i = DataAccessLayer.ExecuteNonQuery("spAddCustomer", CommandType.StoredProcedure,
        DataAccessLayer.CreateParameter("@cuName", SqlDbType.VarChar, cusName),
        DataAccessLayer.CreateParameter("@cuAddress", SqlDbType.VarChar, cusAddress),
        DataAccessLayer.CreateParameter("@cuMobile", SqlDbType.VarChar, cusMobile),
        DataAccessLayer.CreateParameter("@cuImage", SqlDbType.Image, arrImg),
        DataAccessLayer.CreateParameter("@cityId", SqlDbType.Int, cityId),
        DataAccessLayer.CreateParameter("@exist", SqlDbType.Int, null, ParameterDirection.Output));

    DataAccessLayer.Close();

    return i;
}

当用户点击添加一条新记录时插入到表中(tblCustomers

private void btnAU_Click(object sender, EventArgs e)
{
    byte[] imgArr;

    if (PbCustomer.Image == null)
           imgArr = null;
    else
    {
        MemoryStream ms = new MemoryStream();
        PbCustomer.Image.Save(ms, PbCustomer.Image.RawFormat);
        imgArr = ms.ToArray();
    }

    int cityId = int.Parse(cmbCities.SelectedValue.ToString());

    try
    {
        int exist = CustomerClass.spAddCustomer(txtName.Text, txtAddress.Text, txtMobile.Text, imgArr, cityId);

        if (exist == 1)
        {
            MessageBox.Show("A new customer has been saved");
            txtAddress.Text = txtMobile.Text = txtName.Text = "";
            PbCustomer.Image = null;
        }
        else
            MessageBox.Show("A customer with the same mobile number\nalready exists, add new number!");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

但是当我点击Add 按钮(传递空图像)时,我得到了这个错误:

过程或函数“spAddCustomer”需要参数“@cuImage” 没有提供的

尽管表tblCustomers接受空值

【问题讨论】:

  • 你有没有在调试器中单步执行代码来查看实际传入了哪些值?你能把CreateParameter的代码贴出来吗?
  • 请注意,空的TextBox 的值是String.Empty,而不是null!情况会好转吗?您将"" 转换为null
  • 如果 TextBox.Text 是 = 到 string.Empty DataAccessLayer.CreateParameter("@cuName", SqlDbType.VarChar).Value = string.IsNullOrEmpty(cusName) ? DBNULL.Value : cusName;,最好还是这样做
  • ntexttextimage 数据类型将在 SQL Server 的未来版本中删除。避免在新的开发工作中使用这些数据类型,并计划修改当前使用它们的应用程序。请改用nvarchar(max)varchar(max)varbinary(max)See details here
  • 谢谢@marc_s,我知道text,但我不知道image

标签: c# sql-server stored-procedures


【解决方案1】:

刚刚发现可以给存储过程中的参数设置默认值:

ALTER proc [dbo].[spAddCustomer]
@cuName varchar(50)=null,
@cuAddress varchar(50)=null,
@cuMobile varchar(50)= null,
@cuImage image= null,
@cityId int= null,
@exist int output

这解决了我的问题! 这对 PictureBox 中的空图像特别有用,因为我有一个检查空字符串的辅助方法。

【讨论】:

    【解决方案2】:

    您需要检查您的输入是否为空,并在创建参数时使用DBNull.Value。如果您只传递 null 作为参数 - ADO.Net 将忽略它。

    编辑:

    您可以将该检查添加到您的自定义方法DataAccessLayer.CreateParameter()

    【讨论】:

    • DataAccessLayer.CreateParameter("@cuName", SqlDbType.VarChar, String.IsNullOrWhitespace(cusName) ? DBNull.Value : cusName),
    • 我宁愿修复 DataAccessLayer.CreateParameter() 方法本身来检查空/空白参数,而不是使用三元运算符?:每次。
    猜你喜欢
    • 2013-11-19
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2015-04-28
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    相关资源
    最近更新 更多