it-swarm.com.de

Rückgabewert von gespeicherter Prozedur in C # abrufen

Ich habe folgende Anfrage:

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

Dies kompiliert einwandfrei.

In C # möchte ich diese Abfrage ausführen und den Rückgabewert erhalten.

Mein Code ist wie folgt:

  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;

Hinweis: Die Ausnahmebehandlung wurde gekürzt, um den Code kurz zu halten. Jedes Mal, wenn ich in die letzte Zeile komme, wird null zurückgegeben. Was ist der logische Fehler mit diesem Code?

Vielen Dank

64
GurdeepS

Mehrdad macht einige gute Punkte, aber die Hauptsache, die mir aufgefallen ist, ist, dass Sie führen Sie die Abfrage nie aus ...

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

ParameterDirection.ReturnValue sollte für den "Rückgabewert" der Prozedur verwendet werden, keine Ausgabeparameter. Er erhält den von der SQL-Anweisung RETURN zurückgegebenen Wert (mit dem Parameter @RETURN_VALUE).

Anstatt RETURN @b Du solltest SET @b = something

Übrigens ist der Rückgabewertparameter immer int, nicht string.

61
Mehrdad Afshari

Ich hatte jede Menge Probleme mit dem Rückgabewert, also habe ich am Ende nur Dinge ausgewählt.

Die Lösung bestand nur darin, das Ergebnis am Ende auszuwählen und das Abfrageergebnis in Ihrer Funktion zurückzugeben.

In meinem Fall habe ich einen Exists-Check durchgeführt:

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

Dann

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

Sie sollten in der Lage sein, dasselbe mit einem Zeichenfolgenwert anstelle eines Int zu tun.

10
Alan Jackson

Dies baut auf Joels und Mehrdads Antworten auf: Sie binden niemals den Parameter von retval an sqlcommand. Du brauchst ein

sqlcomm.Parameters.Add(retval);

und um sicherzustellen, dass Sie den Befehl ausführen

sqlcomm.ExecuteNonQuery();

Ich bin mir auch nicht sicher, warum Sie 2 Rückgabewert-Strings haben (returnValue und retunvalue).

5
Manatherin

Sie sagen, Ihre SQL kompiliert gut, aber ich bekomme: Muss die skalare Variable "@Password" deklarieren.

Sie versuchen auch, ein varchar (@b) von Ihrer gespeicherten Prozedur zurückzugeben, aber gespeicherte SQL Server-Prozeduren können nur Ganzzahlen zurückgeben.

Wenn Sie die Prozedur ausführen, erhalten Sie den Fehler:

'Konvertierung fehlgeschlagen beim Konvertieren des varchar-Werts' x 'in den Datentyp int.'

4
Martin Brown

Wenn wir einen Wert aus einer gespeicherten Prozedur ohne select-Anweisung zurückgeben. Wir müssen den Befehl "ParameterDirection.ReturnValue" und "ExecuteScalar" verwenden, um den Wert zu erhalten.

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

in 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);
        }

Wir erhalten den zurückgegebenen Wert von SP "IsEmailExists" mit der obigen c # -Funktion.

4

Hier gibt es mehrere Probleme:

  1. Es ist nicht möglich. Sie versuchen einen Varchar zurückzugeben. Rückgabewerte für gespeicherte Prozeduren können nur ganzzahlige Ausdrücke sein. Siehe offizielle RETURN-Dokumentation: https://msdn.Microsoft.com/en-us/library/ms174998.aspx .
  2. Dein sqlcomm wurde nie ausgeführt. Sie müssen sqlcomm.ExecuteNonQuery(); aufrufen, um Ihren Befehl auszuführen.

Hier ist eine Lösung mit OUTPUT-Parametern. Dies wurde getestet mit:

  • 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;
}
3
Djuka

Dies SP sieht sehr seltsam aus. Es ändert nicht, was an @b übergeben wird. Und nirgends in SP weisen Sie @b etwas zu. Und @Password ist nicht definiert, daher funktioniert SP überhaupt nicht.

Ich würde vermuten, dass Sie tatsächlich @Password zurückgeben möchten oder SET @b = (SELECT ...) haben möchten.

Viel einfacher wird es, wenn Sie SP zu (beachten Sie, kein OUTPUT-Parameter) ändern:

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

Dann kann Ihr Code cmd.ExecuteScalar verwenden und das Ergebnis erhalten.

3
Sunny Milenov

Vielleicht hilft das ja.

Datenbankskript:

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

Anwendungskonfigurationsdatei:

<?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>

Datenzugriffsschicht (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();


        }


    }
}

Business Logic Layer (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;

        }

    }
}

Implementierung :

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

Hier müssen zwei Dinge behoben werden. Richten Sie zuerst die gespeicherte Prozedur ein, um den Wert im Ausgabeparameter (nicht im Rückgabeparameter) zu speichern.

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

Dies wird aber das Passwort in @b und Sie werden es als Rückgabeparameter erhalten. Um es in Ihr C # zu bekommen, gehen Sie wie folgt vor:

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();
     }
2
Miles

Sie haben das Konzept von Rückgabewert und Ausgabevariable vertauscht. 1- Ausgangsvariable:

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();
2
Mehran Sarrafi

Wenn Sie verwenden

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

sie müssen dann sicherstellen, dass Ihre gespeicherte Prozedur hat

return @RETURN_VALUE;

am Ende der gespeicherten Prozedur.

1
joey

Angenommen, Sie müssen Username und Password an gespeicherte Prozedur übergeben und wissen, ob die Anmeldung erfolgreich ist oder nicht, und prüfen, ob in gespeicherte Prozedur) ein Fehler aufgetreten ist.

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

Ihre Verbindungszeichenfolge in 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>

Und hier ist die gespeicherte Prozedur als Referenz

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 [email protected] AND [email protected])
            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
0
Sarath Avanavu