从C#中的存储过程获取返回值

我有以下查询:

set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[Validate] @a varchar(50), @b varchar(50) output AS SET @Password = (SELECT Password FROM dbo.tblUser WHERE Login = @a) RETURN @b GO 

这个编译非常好。

在C#中,我想执行这个查询并获得返回值。

我的代码如下:

  SqlConnection SqlConn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyLocalSQLServer"].ConnectionString.ToString()); System.Data.SqlClient.SqlCommand sqlcomm = new System.Data.SqlClient.SqlCommand("Validate", SqlConn); string returnValue = string.Empty; try { SqlConn.Open(); sqlcomm.CommandType = CommandType.StoredProcedure; SqlParameter param = new SqlParameter("@a", SqlDbType.VarChar); param.Direction = ParameterDirection.Input; param.Value = Username; sqlcomm.Parameters.Add(param); SqlParameter retval = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar); retval.Direction = ParameterDirection.ReturnValue; string retunvalue = (string)sqlcomm.Parameters["@b"].Value; 

注:exception处理剪切,以保持代码简短。 每当我到达最后一行,返回null。 这段代码的逻辑错误是什么?

谢谢

Mehrdad提出了一些很好的观点,但我注意到的主要问题是,你从不运行查询

 SqlParameter retval = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar); retval.Direction = ParameterDirection.ReturnValue; sqlcomm.ExecuteNonQuery(); // MISSING string retunvalue = (string)sqlcomm.Parameters["@b"].Value; 
 retval.Direction = ParameterDirection.Output; 

ParameterDirection.ReturnValue应该用于过程的“返回值”,而不是输出参数。 它获取由SQL RETURN语句返回的值(带有名为@RETURN_VALUE的参数)。

而不是RETURN @b你应该SET @b = something

顺便说一句,返回值参数总是int ,而不是string。

我在回报价值方面遇到了很多麻烦,所以最后我只是select了一些东西。

解决scheme只是在最后select结果,并返回查询结果在您的functinon。

在我的情况下,我正在做一个存在检查:

 IF (EXISTS (SELECT RoleName FROM dbo.Roles WHERE @RoleName = RoleName)) SELECT 1 ELSE SELECT 0 

然后

 using (SqlConnection cnn = new SqlConnection(ConnectionString)) { SqlCommand cmd = cnn.CreateCommand(); cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "RoleExists"; return (int) cmd.ExecuteScalar() } 

你应该可以用一个string值而不是int来做同样的事情。

这是build立在Joel和Mehrdad的答案上的:你永远不会把retval的参数绑定到sqlcommand 。 你需要一个

 sqlcomm.Parameters.Add(retval); 

并确保您正在运行该命令

 sqlcomm.ExecuteNonQuery(); 

我也不确定为什么你有2个返回值string( returnValueretunvalue )。

你说你的SQL编译好,但我得到:必须声明标量variables“@Password”。

你也试图从存储过程中返回一个varchar(@b),但是SQL Server存储过程只能返回整数。

当你运行这个程序时,你将会得到这个错误:

将varchar值“x”转换为数据typesint时转换失败

这个SP看起来很奇怪。 它不会修改传递给@b的内容。 而在SP中你没有任何地方给@b分配任何东西。 而且@Password没有定义,所以这个SP根本不起作用。

我猜你实际上是想返回@Password,或有SET @ b =(SELECT …)

如果你修改你的SP(注意,没有OUTPUT参数),会更简单:

 set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[Validate] @a varchar(50) AS SELECT TOP 1 Password FROM dbo.tblUser WHERE Login = @a 

然后,你的代码可以使用cmd.ExecuteScalar,并接收结果。

这里有很多问题:

  1. 这不可能。 你正试图返回一个varchar。 存储过程返回值只能是整数expression式。 请参阅官方RETURN文档: https : //msdn.microsoft.com/en-us/library/ms174998.aspx 。
  2. 你的sqlcomm从未执行过。 你必须调用sqlcomm.ExecuteNonQuery(); 为了执行你的命令。

这是一个使用OUTPUT参数的解决scheme。 这已经过testing:

  • Windows Server 2012
  • .NET v4.0.30319
  • C#4.0
 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[Validate] @a varchar(50), @b varchar(50) OUTPUT AS BEGIN DECLARE @b AS varchar(50) = (SELECT Password FROM dbo.tblUser WHERE Login = @a) SELECT @b; END 
 SqlConnection SqlConn = ... var sqlcomm = new SqlCommand("Validate", SqlConn); string returnValue = string.Empty; try { SqlConn.Open(); sqlcomm.CommandType = CommandType.StoredProcedure; SqlParameter param = new SqlParameter("@a", SqlDbType.VarChar); param.Direction = ParameterDirection.Input; param.Value = Username; sqlcomm.Parameters.Add(param); SqlParameter output = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar); ouput.Direction = ParameterDirection.Output; sqlcomm.ExecuteNonQuery(); // This line was missing returnValue = output.Value.ToString(); // ... the rest of code } catch (SqlException ex) { throw ex; } 

你已经混淆了返回值和输出variables的概念。 1-输出variables:

 Database----->: create proc MySP @a varchar(50), @b varchar(50) output AS SET @Password = (SELECT Password FROM dbo.tblUser WHERE Login = @a) C# ----->: SqlConn.Open(); sqlcomm.CommandType = CommandType.StoredProcedure; SqlParameter param = new SqlParameter("@a", SqlDbType.VarChar); param.Direction = ParameterDirection.Input;//This is optional because Input is the default param.Value = Username; sqlcomm.Parameters.Add(param); SqlParameter outputval = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar); outputval .Direction = ParameterDirection.Output//NOT ReturnValue; string outputvalue = sqlcomm.Parameters["@b"].Value.ToString(); 

有两件事要解决这个问题。 首先设置存储过程以将值存储在输出(不返回)参数中。

 set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[Validate] @a varchar(50), @b varchar(50) output AS SET @b = (SELECT Password FROM dbo.tblUser WHERE Login = @a) RETURN GO 

这将只是密码到@b,你会得到它作为返回参数。 然后把它在你的C#中做到这一点:

 SqlConnection SqlConn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyLocalSQLServer"].ConnectionString.ToString()); System.Data.SqlClient.SqlCommand sqlcomm = new System.Data.SqlClient.SqlCommand("Validate", SqlConn); string returnValue = string.Empty; try { SqlConn.Open(); sqlcomm.CommandType = CommandType.StoredProcedure; SqlParameter param = new SqlParameter("@a", SqlDbType.VarChar, 50); param.Direction = ParameterDirection.Input; param.Value = Username; sqlcomm.Parameters.Add(param); SqlParameter retval = new SqlParameter("@b", SqlDbType.VarChar, 50); retval.Direction = ParameterDirection.ReturnValue; sqlcomm.Parameters.Add(retval); sqlcomm.ExecuteNonQuery(); SqlConn.Close(); string retunvalue = retval.Value.ToString(); } 

可能会有所帮助。

数据库脚本:

 USE [edata] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[InsertNewUser]( @neuname NVARCHAR(255), @neupassword NVARCHAR(255), @neuposition NVARCHAR(255) ) AS BEGIN BEGIN TRY DECLARE @check INT; SET @check = (SELECT count(eid) FROM eusers WHERE euname = @neuname); IF(@check = 0) INSERT INTO eusers(euname,eupassword,eposition) VALUES(@neuname,@neupassword,@neuposition); DECLARE @lastid INT; SET @lastid = @@IDENTITY; RETURN @lastid; END TRY BEGIN CATCH SELECT ERROR_LINE() as errline, ERROR_MESSAGE() as errmessage, ERROR_SEVERITY() as errsevirity END CATCH END 

应用程序configuration文件

 <?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="conStr" value="Data Source=User\SQLEXPRESS;Initial Catalog=edata;Integrated Security=True"/> </appSettings> </configuration> 

数据访问层(DAL):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration; using System.Data; using System.Data.SqlClient; namespace DAL { public static class DAL { public static SqlConnection conn; static DAL() { conn = new SqlConnection(ConfigurationManager.AppSettings["conStr"].ToString()); conn.Open(); } } } 

业务逻辑层(BLL):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; using DAL; namespace BLL { public static class BLL { public static int InsertUser(string lastid, params SqlParameter[] coll) { int lastInserted = 0; try { SqlCommand comm = new SqlCommand(); comm.Connection = DAL.DAL.conn; foreach (var param in coll) { comm.Parameters.Add(param); } SqlParameter lastID = new SqlParameter(); lastID.ParameterName = lastid; lastID.SqlDbType = SqlDbType.Int; lastID.Direction = ParameterDirection.ReturnValue; comm.Parameters.Add(lastID); comm.CommandType = CommandType.StoredProcedure; comm.CommandText = "InsertNewUser"; comm.ExecuteNonQuery(); lastInserted = (int)comm.Parameters[lastid].Value; } catch (SqlException ex) { } finally { if (DAL.DAL.conn.State != ConnectionState.Closed) { DAL.DAL.conn.Close(); } } return lastInserted; } } } 

实现:

 BLL.BLL.InsertUser("@lastid",new SqlParameter("neuname","Ded"), new SqlParameter("neupassword","Moro$ilka"), new SqlParameter("neuposition","Moroz") ); 

当你使用

 cmd.Parameters.Add("@RETURN_VALUE", SqlDbType.Int).Direction = ParameterDirection.ReturnValue; 

你必须确保你的存储过程

 return @RETURN_VALUE; 

在存储过程的末尾。

假设您需要将UsernamePassword传递给存储过程,并知道login是否成功,并检查存储过程是否发生错误。

 public bool IsLoginSuccess(string userName, string password) { try { SqlConnection SQLCon = new SqlConnection(WebConfigurationManager.ConnectionStrings["SqlConnector"].ConnectionString); SqlCommand sqlcomm = new SqlCommand(); SQLCon.Open(); sqlcomm.CommandType = CommandType.StoredProcedure; sqlcomm.CommandText = "spLoginCheck"; // Stored Procedure name sqlcomm.Parameters.AddWithValue("@Username", userName); // Input parameters sqlcomm.Parameters.AddWithValue("@Password", password); // Input parameters // Your output parameter in Stored Procedure var returnParam1 = new SqlParameter { ParameterName = "@LoginStatus", Direction = ParameterDirection.Output, Size = 1 }; sqlcomm.Parameters.Add(returnParam1); // Your output parameter in Stored Procedure var returnParam2 = new SqlParameter { ParameterName = "@Error", Direction = ParameterDirection.Output, Size = 1000 }; sqlcomm.Parameters.Add(returnParam2); sqlcomm.ExecuteNonQuery(); string error = (string)sqlcomm.Parameters["@Error"].Value; string retunvalue = (string)sqlcomm.Parameters["@LoginStatus"].Value; } catch (Exception ex) { } return false; } 

您在Web.Config连接string

 <connectionStrings> <add name="SqlConnector" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=Databasename;User id=yourusername;Password=yourpassword" providerName="System.Data.SqlClient" /> </connectionStrings> 

这里是存储过程供参考

 CREATE PROCEDURE spLoginCheck @Username Varchar(100), @Password Varchar(100) , @LoginStatus char(1) = null output, @Error Varchar(1000) output AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN SET @Error = 'None' SET @LoginStatus = '' IF EXISTS(SELECT TOP 1 * FROM EMP_MASTER WHERE EMPNAME=@Username AND EMPPASSWORD=@Password) BEGIN SET @LoginStatus='Y' END ELSE BEGIN SET @LoginStatus='N' END END END TRY BEGIN CATCH BEGIN SET @Error = ERROR_MESSAGE() END END CATCH END GO