我有以下查询:
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;
注意:切断异常处理以保持代码简短。每当我到达最后一行时,返回null。这段代码的逻辑错误是什么?
由于
答案 0 :(得分:85)
Mehrdad提出了一些好处,但我注意到的主要事情是你永远不会运行查询 ......
SqlParameter retval = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar);
retval.Direction = ParameterDirection.ReturnValue;
sqlcomm.ExecuteNonQuery(); // MISSING
string retunvalue = (string)sqlcomm.Parameters["@b"].Value;
答案 1 :(得分:61)
retval.Direction = ParameterDirection.Output;
ParameterDirection.ReturnValue
应该用于过程的“返回值”,而不是输出参数。它获取SQL RETURN
语句返回的值(使用名为@RETURN_VALUE
的参数)。
而不是RETURN @b
你应该SET @b = something
顺便说一句,返回值参数始终是int
,而不是字符串。
答案 2 :(得分:10)
我在返回值方面遇到了很多麻烦,所以我最后只是选择了一些东西。
解决方案只是在结尾处选择结果并在您的功能中返回查询结果。
在我的情况下,我正在进行存在检查:
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()
}
您应该能够使用字符串值而不是int来执行相同的操作。
答案 3 :(得分:5)
这是基于Joel's和Mehrdad's答案:您永远不会将retval
的参数绑定到sqlcommand
。你需要一个
sqlcomm.Parameters.Add(retval);
并确保您正在运行命令
sqlcomm.ExecuteNonQuery();
我也不确定为什么你有2个返回值字符串(returnValue
和retunvalue
)。
答案 4 :(得分:4)
你说你的SQL编译得很好,但我得到:必须声明标量变量“@Password”。
此外,您尝试从存储过程返回varchar(@b),但SQL Server存储过程只能返回整数。
当您运行该过程时,您将收到错误:
'将varchar值'x'转换为数据类型int'时转换失败。'
答案 5 :(得分:3)
这个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,并接收结果。
答案 6 :(得分:3)
这里有很多问题:
sqlcomm
从未执行过。你必须打电话
sqlcomm.ExecuteNonQuery();
以执行您的命令。这是使用OUTPUT参数的解决方案。测试结果如下:
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;
}
答案 7 :(得分:3)
可能会有所帮助。
数据库脚本:
<?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>
应用程序配置文件:
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();
}
}
}
数据访问层(DAL):
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.BLL.InsertUser("@lastid",new SqlParameter("neuname","Ded"),
new SqlParameter("neupassword","Moro$ilka"),
new SqlParameter("neuposition","Moroz")
);
实施:
=SUMIF('Daily Expense'!A:A,CONCATENATE("2/",B1,"/2017"),'Daily Expense'!B:B)
答案 8 :(得分:3)
当我们从没有select语句的存储过程返回值时。 我们需要使用“ParameterDirection.ReturnValue”和“ExecuteScalar”命令来获取值。
CREATE PROCEDURE IsEmailExists
@Email NVARCHAR(20)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
IF EXISTS(SELECT Email FROM Users where Email = @Email)
BEGIN
RETURN 0
END
ELSE
BEGIN
RETURN 1
END
END
在C#中
GetOutputParaByCommand("IsEmailExists")
public int GetOutputParaByCommand(string Command)
{
object identity = 0;
try
{
mobj_SqlCommand.CommandText = Command;
SqlParameter SQP = new SqlParameter("returnVal", SqlDbType.Int);
SQP.Direction = ParameterDirection.ReturnValue;
mobj_SqlCommand.Parameters.Add(SQP);
mobj_SqlCommand.Connection = mobj_SqlConnection;
mobj_SqlCommand.ExecuteScalar();
identity = Convert.ToInt32(SQP.Value);
CloseConnection();
}
catch (Exception ex)
{
CloseConnection();
}
return Convert.ToInt32(identity);
}
我们使用上面的c#函数获得SP“IsEmailExists”的返回值。
答案 9 :(得分:2)
你混淆了Return Value和Output变量的概念。 1-输出变量:
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();
答案 10 :(得分:2)
有两件事需要解决。首先设置存储过程以将值存储在输出(不返回)参数中。
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();
}
答案 11 :(得分:1)
使用时
C:\Ruby193\bin\scss.bat
然后您必须确保您的存储过程
cmd.Parameters.Add("@RETURN_VALUE", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
在存储过程结束时。
答案 12 :(得分:0)
假设您需要将Username
和Password
传递给存储过程,并知道登录是否成功,并检查存储过程中是否发生错误强>
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
<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
答案 13 :(得分:0)
您尝试获取的值不是返回值,而是输出参数。您需要将参数方向更改为“输出”。
SqlParameter retval = sqlcomm.Parameters.Add("@b", SqlDbType.VarChar);
retval.Direction = ParameterDirection.Output;
command.ExecuteNonquery();
string retunvalue = (string)sqlcomm.Parameters["@b"].Value;
答案 14 :(得分:0)
对于.net core 3.0和dapper:
如果存储过程返回以下内容:
select ID, FILE_NAME from dbo.FileStorage where ID = (select max(ID) from dbo.FileStorage);
然后用c#:
var data = (_dbConnection.Query<FileUploadQueryResponse>
("dbo.insertFile", whateverParameters, commandType: CommandType.StoredProcedure)).ToList();
var storedFileName = data[0].FILE_NAME;
var id = data[0].ID;
如您所见,您可以定义一个简单的类,以帮助从dapper的默认返回结构(我发现无法使用)中检索实际值:
public class FileUploadQueryResponse
{
public string ID { get; set; }
public string FILE_NAME { get; set; }
}
答案 15 :(得分:-1)
此行代码从SQL Server返回Store StoredProcedure返回的值
cmd.Parameters.Add("@id", System.Data.SqlDbType.Int).Direction = System.Data.ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
查询值的执行将从SP返回
id = (int)cmd.Parameters["@id"].Value;