【问题标题】:C# is returning exception: Procedure has no parameters and arguments were suppliedC# 正在返回异常:过程没有参数并且提供了参数
【发布时间】:2016-01-07 16:28:34
【问题描述】:

对于这种格式,我深表歉意。我是编程新手,也是这个网站的新手,所以我会尽量把问题说清楚。

我有一个用于访问/修改客户数据库的网络表单。我有一个用于输入新客户详细信息的按钮,该按钮将通过从数据库中获取最高 ID 号并加一(并发布到表单文本框)来自动分配一个 ID 号。

这是我写的代码:

protected void btnNew_Click(object sender, EventArgs e)
{
        Clear();

        command.Connection = conn;
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "NewCustomer";

        conn.Open();

        SqlParameter maxid = new SqlParameter();
        maxid.ParameterName = "@MaxID";
        maxid.SqlDbType = SqlDbType.Int;
        maxid.Direction = ParameterDirection.Output;
        command.Parameters.Add(maxid);

        command.ExecuteNonQuery();                       

        NewCustId = Convert.ToInt32(maxid.Value);
        NewCustId += 1;

        txtCustID.Text = (NewCustId).ToString();
        txtCustID.DataBind();

        conn.Close();
}

这是存储过程:

CREATE PROCEDURE NewCustomer
    (@MaxID INT OUTPUT)
AS
BEGIN
    SELECT @MaxID = MAX(CustID)
    FROM dbo.Customer
END

我尝试了许多不同的编码方式,但似乎没有任何效果。 我发布的代码在ExecuteNonQuery 有一个异常,说提供了参数并且过程没有参数。当我将command.Parameters.Add(maxid); 放在ExecuteNonQuery 下方时,它返回一个1。

我单独运行 SQL 查询以查看会发生什么,它在未命名的单元格中返回正确答案。由于某种原因,列名出现时会消失。然后,当我尝试使用 C# 代码访问未命名的单元格时,我似乎无法访问它,因为“CustID”列“不存在”。

通过这段代码,我知道SQL命令正在执行,然后C#代码加1,但是我得到的返回值好像是0。

我很感激任何关于如何解决这个问题的想法。谢谢。

编辑:我也试过: 数据表表 = 新数据表(); 适配器。填充(表); NewCustId = table.Rows[0].Field("CustID");

(这里说“CustID”列不存在)

【问题讨论】:

  • 一句话:不要这样做!这将在繁忙的系统中可靠地工作 - 你会得到重复 b> 迟早!相反,请使用 SQL Server 自身更新的INT IDENTITY 列的 SQL Server 内置机制,并确保不要两次使用任何值.....
  • 这行txtCustID.DataBind();有什么用处,你已经在txtCustID.Text = (NewCustId).ToString();这里为文本框赋值,你可以使用txtCustID.Text = Convert.ToString(NewCustId);
  • 我知道您发布了几个“解决方案”,但您应该阅读并注意来自@marc_s 的警告。你正在做的事情将会失败并在未来造成巨大的痛苦。
  • 你需要做的就是以下,编辑你的存储过程SELECT @MaxID = MAX(CustID) FROM dbo.Customer
  • @marc_s 谢谢你的提示。我知道为繁忙的数据库制作唯一 ID 是一种不可靠的方式。不幸的是,我对自动 ID 系统并不熟悉,因为我只是这方面的学生。

标签: c# asp.net sql-server stored-procedures parameters


【解决方案1】:

将您的代码更改为以下内容,然后重试:

 Clear();
    command.Connection = conn;
    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = "NewCustomer";
    conn.Open();
    NewCustId = Convert.ToInt32(cmd.ExecuteScalar().ToString()); 
    NewCustId += 1;
    txtCustID.Text = NewCustId.ToString();
    conn.Close();

你的存储过程是:

CREATE PROCEDURE NewCustomer
(

)
AS
BEGIN
   SELECT MAX(CustID)
     FROM dbo.Customer;
END

【讨论】:

  • @marc_s他想带参数出来,所以我用参数给他看
  • 完美!非常感谢。我是编程新手,所以希望有一个很好的简单解决方案。 (P.S. 我如何选择这个作为我帖子的答案?)
  • @DaveOli 特别是因为您是编程新手,我再次建议您放弃这种方法。这是一个竞争条件。如果您有两个人同时插入新行,您可能会得到不正确的值。这是身份将是一种更好的方法的原因之一。这当然是你的决定,但你会在某个时候感到痛苦,并且试图找出问题所在会让你发疯。
  • @DaveOli 你会后悔走这条路:即使这个应用程序非常小,你最好的办法就是做对,否则当你将相同的解决方案用于现实世界的应用程序并获得并发问题。
  • @SeanLange &Paolo 谢谢。是的,我知道这是一个坏习惯,但我目前还处于学习的初级阶段,并且正在做 Web 开发。稍后我将开设一门单独的 SQL 课程,因此我计划届时更详细地了解良好的数据库协议。谢谢。
【解决方案2】:

ExecuteNonQuery() 预计没有结果。请改用ExecuteReader()

【讨论】:

  • 是的,或者ExectuteScalar()
  • 我试过 ExecuteReader() 和 ExecuteScalar() 都得到了同样的异常信息。
【解决方案3】:

我赞同 marc_S 关于这个问题的说法。 由于您使用最大 ID 并递增 1 以在数据库中插入新记录,因此我建议您在此列中使用 Identity(seed, increment_value)。 这样您就不必找到 max 来插入新记录,并且可以避免很多事务问题。 交易完成后

可能的设计:

Create Table Customer
(
    Id Int Identity(1,1), 
    Name varchar(50)
)
Create Proc NewCustomer 
(
    @Name varchar(50)
)
As
(
    DECLARE @custID Int
    SET NOCOUNT ON
    INSERT INTO Customer (Name) Values('Your Name')
    SET @custID = SCOPE_IDENTITY()
    RETURN @custID
)
protected void btnNew_Click(object sender, EventArgs e)
{
        Clear();
        command.Connection = conn;
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "NewCustomer";

        conn.Open();
        SqlParameter name = new SqlParameter();
        name.ParameterName = "@Name";
        name.Direction = ParameterDirection.Input;
        name.SqlDbType = SqlDbType.Varchar;
        name.Value = "Your Name";
        command.Parameters.Add(name);
        SqlParameter returnValue= new SqlParameter();
        returnValue.ParameterName = "@custID";
        returnValue.SqlDbType = SqlDbType.Int;
        returnValue.Direction = ParameterDirection.ReturnValue;
        command.Parameters.Add(maxid);

        command.ExecuteNonQuery();                       

        NewCustId = Convert.ToInt32(returnValue.Value);

        txtCustID.Text = (NewCustId).ToString();
        txtCustID.DataBind();

        conn.Close();
}

【讨论】:

  • 我也会试一试,看看能不能让它发挥作用。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多