programing

C#에 저장된 프로시저에서 반환 값을 가져오는 중

stoneblock 2023. 6. 23. 21:42

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

이것은 완벽하게 잘 컴파일됩니다.이 쿼리를 실행하여 반환 값을 얻고 싶습니다.내 코드는 다음과 같습니다.

  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이 반환됩니다.이 코드의 논리 오류는 무엇입니까?

메흐다드가 좋은 지적을 해주지만, 제가 주목한 것은 당신이 절대로 질문을 실행하지 않는다는 것입니다.

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현이 아닌

저는 반품 가치에 많은 어려움을 겪었기 때문에 결국 물건을 고르는 것으로 끝이 났습니다.

해결책은 마지막에 결과를 선택하고 쿼리 결과를 함수에 반환하는 것입니다.

제 경우에는 기존 검사를 수행하고 있었습니다.

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 대신 문자열 값으로 동일한 작업을 수행할 수 있어야 합니다.

이것은 Joel과 Mehrdad의 대답을 기반으로 합니다: 당신은 결코 매개변수를 구속하지 않습니다.retval에게sqlcommand당신은 필요합니다.

sqlcomm.Parameters.Add(retval);

명령을 실행하고 있는지 확인합니다.

sqlcomm.ExecuteNonQuery();

저는 또한 당신이 왜 2개의 반환값 문자열을 가지고 있는지 잘 모르겠습니다.returnValue그리고.retunvalue).

SQL 컴파일이 정상이라고 하지만 다음과 같은 경우 스칼라 변수를 "@Password"로 선언해야 합니다.

또한 저장 프로시저에서 varchar(@b)를 반환하려고 하지만 SQL Server 저장 프로시저는 정수만 반환할 수 있습니다.

절차를 실행하면 다음 오류가 발생합니다.

'varchar 값 'x'을(를) 데이터 형식 int로 변환하는 동안 변환하지 못했습니다.'

여기에는 여러 가지 문제가 있습니다.

  1. 불가능합니다.바르샤르를 반환하려고 합니다.저장 프로시저 반환 값은 정수 식만 사용할 수 있습니다.공식 RETURN 문서를 참조하십시오.
  2. 당신의.sqlcomm실행되지 않았습니다.전화해야 합니다.sqlcomm.ExecuteNonQuery();명령을 실행할 수 있습니다.

다음은 OUTPUT 매개 변수를 사용하는 솔루션입니다.이 테스트는 다음을 사용하여 수행되었습니다.

  • 윈도 서버 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;
}

문을 선택하지 않고 Stored procedure에서 값을 반환하는 경우."Parameter Direction"을 사용해야 합니다.값을 가져오려면 "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 "Is Email Exists"의 반환된 값을 얻습니다.

이 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를 사용할 수 있습니다.Scalar를 실행하고 결과를 수신합니다.

이것에 대해 수정해야 할 두 가지가 있습니다.먼저 값을 출력(반환 아님) 파라미터에 저장하도록 저장 프로시저를 설정합니다.

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

응용 프로그램 구성 파일:

<?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")
                 );

반환 값과 출력 변수의 개념을 혼동했습니다. 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();

당신이 합격해야 한다고 가정합니다.Username그리고.PasswordStored Procedure(저장 프로시저)로 이동하여 로그인 성공 여부를 확인하고 Stored Procedure(저장 프로시저)에서 오류가 발생했는지 확인합니다.

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

사용할 때

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

그런 다음 저장 프로시저가 다음을 수행하는지 확인해야 합니다.

return @RETURN_VALUE;

저장 프로시저의 마지막에 표시됩니다.

가져오려는 값은 반환 값이 아니라 출력 매개 변수입니다.파라미터 방향을 Output으로 변경해야 합니다.

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

.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; }
  }

이 코드 라인은 SQL Server에서 반환된 스토어드 프로시저 값을 반환합니다.

cmd.Parameters.Add("@id", System.Data.SqlDbType.Int).Direction = System.Data.ParameterDirection.ReturnValue;                
cmd.ExecuteNonQuery();

SP에서 쿼리 값의 실행이 반환됩니다.

id = (int)cmd.Parameters["@id"].Value;

언급URL : https://stackoverflow.com/questions/706361/getting-return-value-from-stored-procedure-in-c-sharp