过程或函数 'uspExportGetMailinfoTest' 需要未提供的参数“@CUSTOMER”。我错过了什么?

Procedure or function 'uspExportGetMailinfoTest' expects parameter '@CUSTOMER', which was not supplied. What am I missing?

我在 Visual Studio 2017 年使用 C# Winforms 工作。该项目基于从 VB6 到 C# 的转换,但现在我遇到了一个错误,它说我没有提供参数。但据我所知,我似乎有。

我遇到的错误是:

Procedure or function 'uspExportGetMailinfoTest' expects parameter '@CUSTOMER', which was not supplied.

我不知道是因为我的 C# 代码还是我遗漏了 SQL 中的某些内容。我想知道是否有人可以描述我做错了什么。我也总是乐于接受任何简化我的代码的建议。

C#:

SqlConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString);

public bool getMailInfo(string sCustomer, ref string sMailTo, ref string sSubject, ref string sMsg)
{
    try
    {
        SqlDataAdapter commSql = null;
 
        DataSet ds = new DataSet();

        db.Open();

        string sSql = "uspExportGetMailinfoTest";
                
        SqlCommand cmd = new SqlCommand("uspExportGetMailinfoTest", db);
        cmd.CommandType = CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("@CUSTOMER", sCustomer);

        cmd.ExecuteNonQuery();
              
        commSql = new SqlDataAdapter(sSql, db);
        commSql.Fill(ds, "list");

        if (ds.Tables["list"].Rows.Count > 0)
        {
            cmd.Parameters.AddWithValue("mailto", sMailTo);
            cmd.Parameters.AddWithValue("subject", sSubject);

            cmd.ExecuteNonQuery();
            db.Close();
        }
        else
        {
            sMsg = "getMailInfo returns blank";
            db.Close();
        }

        return true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;
    }
}

此存储过程正在从另一个存储过程中恢复“客户密钥”。根据获得的密钥,它会决定哪个客户将收到邮件。

存储过程:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[uspExportGetMailinfoTest] 
    @CUSTOMER AS nvarchar(50)
AS
    IF @CUSTOMER IN ('200600', '200600-SEK', '200600-USD', '200602', '200603', '200604', '200606') --2021-01-19 added 200606 --added ,'200603','200604' 20017-04-28
    BEGIN
        SELECT
            '\XYXYX\MansTest' AS mailto,
            'DELIVERY TO XYXYX' AS subject                  
    END

AddWithValue 替换了接受字符串和对象的 SqlParameterCollection.Add 方法。采用字符串和对象的 Add 重载已被弃用,因为采用字符串和 SqlDbType 枚举值的 SqlParameterCollection.Add 重载可能存在歧义,其中传递带有字符串的整数可以被解释为参数值或相应的 SqlDbType 值。每当您想通过指定参数的名称和值来添加参数时,都可以使用 AddWithValue。 改用:

    cmd.Parameters.Add("@CUSTOMER", SqlDbType.NVarChar, 50);
    cmd.Parameters["@CUSTOMER"].Value = sCustomer;

如果你想使用带参数的数据适配器,你需要向它传递一个 SqlCommand 包含参数的对象。

您的代码还有很多其他问题:

  • 所有 Sql 个对象需要在 using 个块中
  • 不缓存连接对象,需要时创建,用using处理。请注意,如果您有 using 块,则无需调用 Close()
  • 您正在调用 ExecuteNonQuery(多次),return 没有结果
  • 单行结果不会在参数中返回,它是一个结果集
  • 您可以从 DataSet 中读取该行,但实际上使用 DataReader
  • 更容易
  • 不要使用AddWithValue,明确指定参数类型和长度
  • 连接打开时不要用 MessageBox 阻塞。
public bool getMailInfo(string sCustomer, ref string sMailTo, ref string sSubject, ref string sMsg)
{
    try
    {
        using (SqlConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString))
        using (SqlCommand cmd = new SqlCommand("uspExportGetMailinfoTest", db) {CommandType = CommandType.StoredProcedure})
        {
            cmd.Parameters.Add("@CUSTOMER", SqlDbType.NVarChar, 50).Value = sCustomer;
            db.Open();
            using (var reader = cmd.ExecuteReader())
            {
                if (reader.Read())
                {
                    sMailTo = (string)reader["mailto"];
                    sSubject = (string)reader["subject"];
                }
                else
                {
                    sMsg = "getMailInfo returns blank";
                }

                return true;
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;
    }
}

对于多行,您将使用 while (reader.Read())

对于单行单列结果,您可以删除 reader 并使用 cmd.ExecuteScalar()