views:

4906

answers:

5

Probably an easy-to-answer question. I have this procedure:

CREATE PROCEDURE [dbo].[AccountExists]
    @UserName nvarchar(16)
AS
IF EXISTS (SELECT Id FROM Account WHERE UserName=@UserName)
SELECT 1
ELSE SELECT 0

When I have ADO.NET code that calls this procedure and does this:

return Convert.ToBoolean(sproc.ExecuteScalar());

Either true or false is returned.

When I change the stored procedure to RETURN 1 or 0 instead of SELECT:

ALTER PROCEDURE [dbo].[AccountExists]
    @UserName nvarchar(16)
AS
IF EXISTS (SELECT Id FROM Account WHERE UserName=@UserName)
RETURN 1
ELSE RETURN 0

sproc.ExecuteScalar() returns null. If I try sproc.ExecuteNonQuery() instead, -1 is returned.

How do I get the result of a stored procedure with a RETURN in ADO.NET?

I need AccountExists to RETURN instead of SELECT so I can have another stored procedure call it:

--another procedure to insert or update account

DECLARE @exists bit

EXEC @exists = [dbo].[AccountExists] @UserName 

IF @exists=1
--update account
ELSE
 --insert acocunt
+15  A: 

Add a parameter to the command, using ParameterDirection.ReturnValue. The return value will be present in the paramter after the execution.

John Saunders
A: 

If you are planing on using it like the example below AccountExists might be better off as a function.

Otherwise you should still be able to get the result of the stored procedure by calling it from another one by doing a select on the result.

Luke Lowrey
+1  A: 

ExecuteScalar returns the first column of the first row. Since you were no longer selecting, and creating a resultset, that is why it was returning null. Just as FYI. John Saunders has the correct answer.

Darren Kopp
A: 

Just some advice, but by default, a Stored Procedure returns 0 unless you specify something else. For this reason, 0 is often used to designate success and non-zero values are used to specify return error conditions. I would go with John's suggestion, or use an output parameter

Russ Cam
+2  A: 

Also, to retrieve the result (or any other output parameter for that matter) from ADO.NET you have to loop through all returned result sets first (or skip them with NextResult)

This means that if you have a procedure defined like this:

CREATE PROC Test(@x INT OUT) AS
    SELECT * From TestTable
    SELECT @x = 1

And try to do this:

SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Test"
cmd.Parameters.Add("@x", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@retval", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;

cmd.Execute();
int? x = cmd.Parameters["@x"].Value is DBNull ? null : (int?)cmd.Parameters["@x"].Value;

Then x will contain null. To make it work, you have to execute the procedure like:

using (var rdr = cmd.ExecuteReader()) {
    while (rdr.Read())
        MaybeDoSomething;
}
int? x = cmd.Parameters["@x"].Value is DBNull ? null : (int?)cmd.Parameters["@x"].Value;

In the latter case, x will contain 1 as expected.

erikkallen
@erikkallen: you might want to clarify that you mean it's necessary to loop through all result sets that involved calls to stored procedures with output or return value parameters.
John Saunders