C# 将参数传递给SQL Server存储过程

C# 将参数传递给SQL Server存储过程,c#,sql-server,C#,Sql Server,我试图在我的应用程序中向存储过程传递一个参数,但我不知道我做错了什么。我犯了一个错误 过程或函数“usp_GetFrowerDetails”需要未提供的参数“@BookID” 当我路过的时候,我做了很多事情,但仍然没有找到解决办法 这是我的代码: IDataReader reader = null; SqlCommand command = new SqlCommand(); try { SqlConnection connection = GetDBConnection();

我试图在我的应用程序中向存储过程传递一个参数,但我不知道我做错了什么。我犯了一个错误

过程或函数“usp_GetFrowerDetails”需要未提供的参数“@BookID”

当我路过的时候,我做了很多事情,但仍然没有找到解决办法

这是我的代码:

IDataReader reader = null;

SqlCommand command = new SqlCommand();

try
{
    SqlConnection connection = GetDBConnection();

    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = Constants.SP_BookBorrowerDetails;
    command = new SqlCommand(command.CommandText, connection);

    command.Parameters.AddWithValue("@BookID", bookID);

    reader = base.ExecuteReader(command);
}
catch (System.Data.SqlClient.SqlException ex)
{
    throw new Exception("Oops! Something went wrong.");
}
下面是我的存储过程:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[usp_getBorrowerDetails]
    @BookID INT
AS
    SELECT 
        Name, Mobile, ReturnDate 
    FROM
        BorrowerDetails 
    INNER JOIN
        BookDetails ON BookDetails.CurrentBorrowerID = BorrowerDetails.ID    
    WHERE
        BookDetails.BookID = @BookID
GO

如果我运行任何不需要任何参数的存储过程,它就可以正常工作。只有在添加参数时才会出现问题。

这里的一种可能性是
bookID
null

Convert.ToString(null)
返回:
null

未附加值为
null
的参数。为此,需要使用
DBNull.Value

但是:无论如何,也没有必要把它变成
字符串

考虑使用:
(对象)bookId??将DBNull.Value
改为值,这将解决这两个问题


编辑:如注释中所述,您还过早地设置了
CommandType
,然后替换了命令对象;设置
命令类型
必须在
新建
-d变量后进行


注意:这些只是“整洁”能帮助你的许多事情中的两件;考虑:

var reader = connection.ExecuteReader(
      "usp_getBorrowerDetails", new { BookID = bookID },
      commandType: CommandType.StoredProcedure);

(虽然我通常会提倡dapper的
查询方法,但它们也为您做了很多事情)

这里的一种可能性是
bookID
null

Convert.ToString(null)
返回:
null

未附加值为
null
的参数。为此,需要使用
DBNull.Value

但是:无论如何,也没有必要把它变成
字符串

考虑使用:
(对象)bookId??将DBNull.Value
改为值,这将解决这两个问题


编辑:如注释中所述,您还过早地设置了
CommandType
,然后替换了命令对象;设置
命令类型
必须在
新建
-d变量后进行


注意:这些只是“整洁”能帮助你的许多事情中的两件;考虑:

var reader = connection.ExecuteReader(
      "usp_getBorrowerDetails", new { BookID = bookID },
      commandType: CommandType.StoredProcedure);

(虽然我通常会提倡dapper的
查询方法,但它们也为您提供了更多功能)

问题之一是代码的顺序。您正在将命令设置为新的SqlCommand。发生这种情况时,默认的CommandType为Text

command = new SqlCommand(command.CommandText, connection);
command.CommandType = CommandType.StoredProcedure;
command.CommandText = Constants.SP_BookBorrowerDetails;

您应该首先创建命令,然后设置属性。

问题之一是代码的顺序。您正在将命令设置为新的SqlCommand。发生这种情况时,默认的CommandType为Text

command = new SqlCommand(command.CommandText, connection);
command.CommandType = CommandType.StoredProcedure;
command.CommandText = Constants.SP_BookBorrowerDetails;

您应该首先创建命令,然后设置属性。

在设置了
CommandType
CommandText
之后,您将
命令重新定义为全新的
SqlCommand
,这意味着它将被视为纯SQL,而不是存储过程。在适当的位置创建一次

IDataReader reader = null;
SqlCommand command;

try
{
    SqlConnection connection = GetDBConnection();

    command = new SqlCommand(Constants.SP_BookBorrowerDetails, connection);
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.AddWithValue("@BookID", bookID);

    reader = base.ExecuteReader(command);
}
catch (System.Data.SqlClient.SqlException ex)
{
    throw new Exception("Oops! Something went wrong.");
}

顺便说一句,您可能还应该考虑不只是保持连接打开,而是在一个方法中获得结果,而不是依赖调用代码来管理连接。

在设置了
CommandType
CommandText
之后,您将
命令重新定义为全新的
SqlCommand
,这意味着它将被视为纯SQL,而不是存储过程。在适当的位置创建一次

IDataReader reader = null;
SqlCommand command;

try
{
    SqlConnection connection = GetDBConnection();

    command = new SqlCommand(Constants.SP_BookBorrowerDetails, connection);
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.AddWithValue("@BookID", bookID);

    reader = base.ExecuteReader(command);
}
catch (System.Data.SqlClient.SqlException ex)
{
    throw new Exception("Oops! Something went wrong.");
}

另一方面,您可能还应该考虑不只是保持连接打开,而是在一个方法中获取结果,而不是依赖调用代码来管理连接。

我相信您已经将Constants.SP_bookbrowerDetails声明为“EXEC[dbo].[usp_getbrowerDetails]”,它没有预期的输入参数“@BookID”

Command.Parameters.AddWithValue,它将只接受需要传递的参数名称和值。但它仍然需要Constants.SP_BookFrooderDetails语法中的参数,因为在执行命令文本时,“Command.Parameters”中的可用参数列表需要具有相同名称的映射参数

using (SqlConnection connection = new SqlConnection("SQL connection string"))
        {
            connection.Open();
            try
            {
                SqlCommand command = new SqlCommand("EXEC [dbo].[usp_getBorrowerDetails] @BookID", connection);
                command.CommandType = CommandType.StoredProcedure;
                command = new SqlCommand(command.CommandText, connection);
                command.Parameters.AddWithValue("@BookID", 1);

                IDataReader reader = command.ExecuteReader();
            }
            catch (SqlException ex)
            {
                throw new Exception("Oops! Something went wrong." + ex.Message);
            }
        }
请检查上面的代码片段


如果出现任何问题,请返回。

我相信您已将Constants.SP_bookbrowerdetails声明为“EXEC[dbo].[usp_getbrowerdetails]”,它没有预期的输入参数“@BookID”

Command.Parameters.AddWithValue,它将只接受需要传递的参数名称和值。但它仍然需要Constants.SP_BookFrooderDetails语法中的参数,因为在执行命令文本时,“Command.Parameters”中的可用参数列表需要具有相同名称的映射参数

using (SqlConnection connection = new SqlConnection("SQL connection string"))
        {
            connection.Open();
            try
            {
                SqlCommand command = new SqlCommand("EXEC [dbo].[usp_getBorrowerDetails] @BookID", connection);
                command.CommandType = CommandType.StoredProcedure;
                command = new SqlCommand(command.CommandText, connection);
                command.Parameters.AddWithValue("@BookID", 1);

                IDataReader reader = command.ExecuteReader();
            }
            catch (SqlException ex)
            {
                throw new Exception("Oops! Something went wrong." + ex.Message);
            }
        }
请检查上面的代码片段

如果出现任何问题,请回复。

这是我的工作

connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand  com  = new SqlCommand("usp_getBorrowerDetails", connection);
com.CommandType = CommandType.StoredProcedure;

com.Parameters.AddWithValue("@BookID", bookID);

IDataReader reader = com.ExecuteReader();

while (reader.Read())
{
   
}

reader.Close();
connection.Close();
这是我的工作

connection = new SqlConnection(connectionString);
connection.Open();
SqlCommand  com  = new SqlCommand("usp_getBorrowerDetails", connection);
com.CommandType = CommandType.StoredProcedure;

com.Parameters.AddWithValue("@BookID", bookID);

IDataReader reader = com.ExecuteReader();

while (reader.Read())
{
   
}

reader.Close();
connection.Close();

不要使用
常量中的AddWithValue。SP_bookbrowerDetails
?这不是答案,但您确实需要将连接包装在USING子句中。按照编码,您的连接未正确关闭和处理,这可能导致连接池被消耗。@PeterB这不是我将其更改为bookID As的情况well@SeanLangeSqlCommand对象也一样,不要使用AddWithValue,常量中的内容。SP_bookbrowerdetails
?不是答案,但确实需要包装您的连接在USING子句中。按照编码,您的连接未正确关闭和处理,这可能导致连接池被消耗。@PeterB这不是我将其更改为bookID As的情况well@SeanLange与SqlCommand对象相同,他还应该在创建新命令后设置commandtype和文本,而不是在更新代码和remo之前