C# C-SQL Server存储过程-参考?

C# C-SQL Server存储过程-参考?,c#,sql,sql-server,stored-procedures,C#,Sql,Sql Server,Stored Procedures,我目前正在使用C、SQL Server并编写一个Web API应用程序 我正在创建SQL Server存储过程,有几个工作步骤,包括插入数据库,以及更新数据库中的条目。然而,我现在正在尝试处理输出,并且正在努力处理一些简单的事情 我希望传入一个电子邮件地址,并返回第一个匹配的行id 以下是存储过程: CREATE PROCEDURE USER_PROCEDURE_GET_ID @Email VARCHAR(200), @id int Out AS SELECT *

我目前正在使用C、SQL Server并编写一个Web API应用程序

我正在创建SQL Server存储过程,有几个工作步骤,包括插入数据库,以及更新数据库中的条目。然而,我现在正在尝试处理输出,并且正在努力处理一些简单的事情

我希望传入一个电子邮件地址,并返回第一个匹配的行id

以下是存储过程:

CREATE PROCEDURE USER_PROCEDURE_GET_ID
    @Email VARCHAR(200),
    @id int Out
AS
    SELECT * 
    FROM [dbo].[Users]
    WHERE Email = @Email

    SET @id = id

    RETURN @id
这是C代码

public int GetID( string emailAddress )
{
// Create an SQL command
SqlCommand command = new SqlCommand();
command.Connection = this.sqlConnection;
// Set the command type to use a stored procedure
command.CommandType = CommandType.StoredProcedure;
// The name of the stored procedure
command.CommandText = "USER_PROCEDURE_GET_ID";

// Add the email address
command.Parameters.Add( new SqlParameter( "@email", emailAddress ) );

// Add the output param
SqlParameter outputParam = new SqlParameter( "@id", SqlDbType.Int )
{
    Direction = ParameterDirection.Output
};
command.Parameters.Add( outputParam );

// Create the reader
SqlDataReader reader = null;

// Execute the command
try
{
    reader = command.ExecuteReader();
}
catch (InvalidCastException ex)
{
}
catch (SqlException ex)
    {
}
catch (InvalidOperationException ex)
{
}
catch (IOException ex)
{
}
finally
{
       reader.Close();
    }

Debug.Write( "user id: " + outputParam.Value.ToString() );

return 0;
}
我知道我没有正确处理异常,也没有对返回的值执行任何操作。此时,我没有得到返回的值,也得到一个错误:

System.NullReferenceException:对象引用未设置为对象的实例


提前感谢。

我不确定这里的内容是否正确,也不确定如何设置@id output参数,但我也相信有一种更简单的方法可以满足您的要求。当您说您只需要第一行的单个值时,听起来好像您想使用ExecuteScalar而不是带有输出参数的读取器,因为关于输出参数和结果集有一些奇怪的要求,我不记得了

我想说你应该做的就是这样

object result = command.ExecuteScalar("SELECT TOP 1 Id FROM [dbo].[Users] WHERE Email = @Email");
if (!DBNull.Value.Equals(result)) return (int)value;

// return whatever value you want for "no-match" here

我不确定这里的内容是否正确,也不确定如何设置@id输出参数,但我也相信有一种更简单的方法可以满足您的要求。当您说您只需要第一行的单个值时,听起来好像您想使用ExecuteScalar而不是带有输出参数的读取器,因为关于输出参数和结果集有一些奇怪的要求,我不记得了

我想说你应该做的就是这样

object result = command.ExecuteScalar("SELECT TOP 1 Id FROM [dbo].[Users] WHERE Email = @Email");
if (!DBNull.Value.Equals(result)) return (int)value;

// return whatever value you want for "no-match" here

您需要在select子句中设置@id,并且不返回它,因为它是一个out参数

CREATE PROCEDURE USER_PROCEDURE_GET_ID
@Email varchar(255),
@id int Out
AS

SELECT @id = id FROM [dbo].[Users]
WHERE Email = @Email

不过,这实际上不需要存储过程。只是。

您需要在select子句中设置@id,并且您也不返回它,因为它是一个out参数

CREATE PROCEDURE USER_PROCEDURE_GET_ID
@Email varchar(255),
@id int Out
AS

SELECT @id = id FROM [dbo].[Users]
WHERE Email = @Email

不过,这实际上不需要存储过程。只是。

什么时候会出现错误?是不是当你调用ExēcuteReader时?但是当你设置@ID时,你在sp中从哪里获得该ID?@PM,没错。Steve我想我是从数据库字段中获取ID的。我刚从其他语言进入C语言,我以前使用SQL的唯一经验是使用PHP。。所以我对这台自动取款机有点陌生。我的猜测是你没有得到任何回报,然后尝试读取它是什么,它是空的。您是否尝试过在cmd.ExecuteReader之前获取值,然后运行该查询?它的回报是什么?此外,您应该能够只返回@@IDENTITY,但阅读此线程可能有助于确定这一点。在什么情况下会出现错误?是不是当你调用ExēcuteReader时?但是当你设置@ID时,你在sp中从哪里获得该ID?@PM,没错。Steve我想我是从数据库字段中获取ID的。我刚从其他语言进入C语言,我以前使用SQL的唯一经验是使用PHP。。所以我对这台自动取款机有点陌生。我的猜测是你没有得到任何回报,然后尝试读取它是什么,它是空的。您是否尝试过在cmd.ExecuteReader之前获取值,然后运行该查询?它的回报是什么?您还应该能够只返回@@IDENTITY,但阅读此线程可能会有助于确定这一点。这就成功了!另外一个愚蠢的错误是我将电子邮件设置为int,而不是VARCHAR,愚蠢的打字错误。感谢大家的快速回复!而且我可以问一下为什么我应该避免存储过程吗?我一直在阅读有关SQL注入预防的书籍,而存储过程似乎是我的方向。除非我对它有点着迷,不需要将它用于查询类型语句?只要在查询中使用参数SqlParameter,就不需要担心sql注入。如果使用不带参数的存储过程,仍然可能存在注入问题。示例字符串sql=exec USER_PROCEDURE_GET_ID'+emailString+';这是我的假设,但我的一个朋友建议使用存储过程+参数。谢谢你的额外建议,真的很感激。这就成功了!另外一个愚蠢的错误是我将电子邮件设置为int,而不是VARCHAR,愚蠢的打字错误。感谢大家的快速回复!而且我可以问一下为什么我应该避免存储过程吗?我一直在阅读有关SQL注入预防的书籍,而存储过程似乎是我的方向。除非我对它有点着迷,不需要将它用于查询类型语句?只要在查询中使用参数SqlParameter,就不需要担心sql注入。如果使用不带参数的存储过程,仍然可能存在注入问题。示例字符串sql=exec USER\u PROCE
在获取ID'+emailString+'期间;这是我的假设,但我的一个朋友建议使用存储过程+参数。谢谢你的额外建议,真的很感谢。我不是专门找第一行,我只是想为电子邮件与传入内容匹配的用户检索该行的id。不过我很想听到更多,谢谢你,你可能只会有一排出来,对吧?即使使用输出参数,也只能使用一个值。没错,一行。谢谢,我不是专门寻找第一行,我是想为电子邮件与传入内容匹配的用户检索该行的id。不过我很想听到更多,谢谢你,你可能只会有一排出来,对吧?即使使用输出参数,也只能使用一个值。没错,一行。谢谢