Avatar billede anders_cp Nybegynder
31. juli 2008 - 18:20 Der er 14 kommentarer og
1 løsning

hente data fra Stored Procedures output-parameter

Hejsa
Jeg har indsat et udpluk af min stored procedure, som jeg mener er nok til at forstå mit spørgsmål:


ALTER PROCEDURE [dbo].[nlx_RecievedReturnnumber]
(
    @ActivityID INT,
    @iReturnedStuff bit OUTPUT
)
AS

    DECLARE @PartorderStatusID16 INT
    DECLARE @PartorderStatus16WithReturnNumber INT


// meningen er at jeg har en input-param: activityid og en output-param: iReturnedStuff
.
.
.
.


IF (@PartorderStatus16WithReturnNumber - @PartorderStatusID16 = 0)
BEGIN
    SET @iReturnedStuff = 1
END

ELSE
BEGIN
    SET @iReturnedStuff = 0
END
PRINT @iReturnedStuff


Jeg ønsker så returneret iReturnedStuff til min C#-appl:
        public bool RecievedReturnnumber(int activityID)
        {
            SqlConnection connection = new SqlConnection(this.ConnectionString);
            SqlCommand command = new SqlCommand();
            command.Connection = connection;
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "nlx_RecievedReturnnumber";
            command.Parameters.AddWithValue("@ActivityID", activityID);


            SqlParameter param = new SqlParameter("@iReturnedStuff", System.Data.SqlDbType.Char, 1);
            param.Direction = ParameterDirection.Output;
            command.Parameters.Add(param);

            connection.Open();
            bool allReturnedNumbered = Convert.ToBoolean(command.ExecuteScalar());

            connection.Close(); connection = null; command = null;
            return allReturnedNumbered;
        }



Jeg får desværre altid returneret falsk. Hvad gør jeg galt?
Avatar billede arne_v Ekspert
31. juli 2008 - 18:24 #1
Jeg forstaar ikke din kode.

Din SP har en OUT parameter. Men ingen result set og ingen retur vaerdi.

Din C# henter en vaerdi fra result set men bruger ikke OUT parameter eller retur vaerdi.
Avatar billede arne_v Ekspert
31. juli 2008 - 18:25 #2
Jeg lavede et eksempel til et andet stpoergsmaal for 4 aar siden.

CREATE PROCEDURE TEST_OUTRSRET
@outarg INTEGER OUTPUT
AS
SELECT @outarg = 123
SELECT * FROM T1
RETURN 456
GO


using System;
using System.Data;
using System.Data.SqlClient;

class MainClass
{
    public static void Main(string[] args)
    {
        SqlConnection con = new SqlConnection("server=ARNEPC2;Integrated Security=SSPI;database=Test");
        con.Open();
        SqlCommand cmd = new SqlCommand("TEST_OUTRSRET", con);
        cmd.CommandType = CommandType.StoredProcedure;
        SqlParameter prm = new SqlParameter("@outarg", SqlDbType.Int, 0, "outarg");
        prm.Direction = ParameterDirection.Output;
        cmd.Parameters.Add(prm);
        SqlParameter ret = new SqlParameter("@retval", SqlDbType.Int);
        ret.Direction = ParameterDirection.ReturnValue;
        cmd.Parameters.Add(ret);
        SqlDataReader rdr = cmd.ExecuteReader();
        while(rdr.Read())
        {
            Console.WriteLine(rdr[0] + " " + rdr[1]);
        }
        rdr.Close();
        Console.WriteLine((int)cmd.Parameters["@outarg"].Value);
        Console.WriteLine((int)cmd.Parameters["@retval"].Value);
        con.Close();
    }
}
Avatar billede anders_cp Nybegynder
31. juli 2008 - 19:22 #3
MIn stored procedure skal kun returnere een værdi, skal der så være result set?
SP-virker fint når jeg eksekverer den fra MS-SQL-manegeren. Jeg paster lige hele SP (måske det hjælper på forståelsen):

ALTER PROCEDURE [dbo].[nlx_RecievedReturnnumber]
(
    @ActivityID INT,
    @iReturnedStuff bit OUTPUT
)
AS

    DECLARE @PartorderStatusID16 INT
    DECLARE @PartorderStatus16WithReturnNumber INT

SET @PartorderStatusID16 =(
SELECT COUNT(*)
FROM PartOrderStatus INNER JOIN PartOrders ON PartOrderStatus.PartOrderStatusID = PartOrders.PartOrderStatusID
WHERE ActivityID = @ActivityID AND PartOrders.PartOrderStatusID = 16
)


SET @PartorderStatus16WithReturnNumber = (
SELECT COUNT(PartVendorReturnReferenceNumber)
FROM PartOrderStatus INNER JOIN PartOrders ON PartOrderStatus.PartOrderStatusID = PartOrders.PartOrderStatusID
WHERE ActivityID = @ActivityID AND PartOrders.PartOrderStatusID = 16
)
IF (@PartorderStatus16WithReturnNumber - @PartorderStatusID16 = 0)
BEGIN
    SET @iReturnedStuff = 1
END

ELSE
BEGIN
    SET @iReturnedStuff = 0
END

I dit eksempel bruger du dataset og datareader. Skal jeg også bruge det(når der kun returneres een værdi)?
I dit eksempel er der ikke noget input - men det er måske bare en detalje der kan mingeleres ind...

Du skrive at min c#-kode henter data fra et result set. Det kan jeg ikke se den gør (har ikke brugt datareader men ExecuteScalar(), som jo kun returnere een værdi og ikke et dataset).

Du har sikkert ret i hvad du skriver, men jeg forstår det måske ikke.
Avatar billede anders_cp Nybegynder
31. juli 2008 - 19:29 #4
Eksempel på eksekvering fra ms-sql:
GO

DECLARE    @return_value int,
        @iReturnedStuff bit

EXEC    @return_value = [dbo].[nlx_RecievedReturnnumber]
        @ActivityID = 207775,
        @iReturnedStuff = @iReturnedStuff OUTPUT

SELECT    @iReturnedStuff as N'@iReturnedStuff'

SELECT    'Return Value' = @return_value

GO


returner:
@iReturnedStuff
---------------
1

(1 row(s) affected)

Return Value
------------
0

(1 row(s) affected)


@iReturnedStuff = 1 er sand, som det skal give.
Avatar billede arne_v Ekspert
31. juli 2008 - 20:21 #5
ExecuteScalar() henter foerste kolonne fra foerste raekke af foerste result set !!!!
Avatar billede arne_v Ekspert
31. juli 2008 - 20:23 #6
Jeg gaetter paa at:

bool allReturnedNumbered = Convert.ToBoolean(command.ExecuteScalar());

skal vaere:

bool allReturnedNumbered = Convert.ToBoolean(command.Parameters["@iReturnedStuff"].Value);
Avatar billede arne_v Ekspert
31. juli 2008 - 20:24 #7
evt. skal erklaeringen af parameteren i C# koden aendres fra char til bit
Avatar billede anders_cp Nybegynder
31. juli 2008 - 20:51 #8
Har gjort som du skriver, men returnerer fortsat kun falsk :-(

        public bool RecievedReturnnumber(int activityID)
        {
            SqlConnection connection = new SqlConnection(this.ConnectionString);
            SqlCommand command = new SqlCommand();
            command.Connection = connection;
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "nlx_RecievedReturnnumber";
            command.Parameters.AddWithValue("@ActivityID", activityID);

            SqlParameter param = new SqlParameter("@iReturnedStuff", System.Data.SqlDbType.Bit, 1);
            param.Direction = ParameterDirection.Output;
            command.Parameters.Add(param);

            connection.Open();
            bool allReturnedNumbered = Convert.ToBoolean(command.Parameters["@iReturnedStuff"].Value);

            connection.Close(); connection = null; command = null;
            return allReturnedNumbered;
        }



Har du nogen idé(er), eller skal jeg prøve med dit oprindelige forslag?
Avatar billede arne_v Ekspert
31. juli 2008 - 21:10 #9
Proev lige foerst og saet et:

command.ExecuteNonQuery();

ind lige efter Open !
Avatar billede anders_cp Nybegynder
31. juli 2008 - 21:27 #10
Nu returnerer alt true
connection.Open();
command.ExecuteNonQuery();
bool allReturnedNumbered = Convert.ToBoolean(command.Parameters["@iReturnedStuff"].Value);

Jeg har debugget og set at command.Parameters["@iReturnedStuff"].Value returnerer true (også når det skal returnere false
Avatar billede anders_cp Nybegynder
31. juli 2008 - 21:36 #11
Har prøvet en variant af dit eksempel:

Stored Procedure:
ALTER PROCEDURE [dbo].[TEST_OUTRSRET]
@outarg INTEGER OUTPUT
AS
SELECT @outarg = 123
SELECT * FROM vendors
RETURN 456

Det er værdien 456 som jeg ønsker (hvis jeg skal kunne overføre eksemplet til mit eget):

C-sharp-koden:

        public int RecievedReturnnumber(int activityID)
        {
            int allReturnedNumbered = 0;
            SqlConnection connection = new SqlConnection(this.ConnectionString);
            SqlCommand command = new SqlCommand();
            command.Connection = connection;
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "TEST_OUTRSRET";
           
            SqlParameter prm = new SqlParameter("@outarg", SqlDbType.Int, 0, "outarg");
            prm.Direction = ParameterDirection.Output;
            command.Parameters.Add(prm);

            connection.Open();
            SqlDataReader rdr = command.ExecuteReader();
            while (rdr.Read())
            {
                allReturnedNumbered = Convert.ToInt32(rdr[0]);
            }

            connection.Close(); connection = null; command = null;
            return allReturnedNumbered;
        }

Jeg får resultatet 33 som svarer til antallet af rækker i SELECT * FROM vendors i sql'en fra SP.
Det er imidlertid retur-værdien jeg ønsker. Måske du kan hjælpe mig herfra
Avatar billede anders_cp Nybegynder
31. juli 2008 - 22:37 #12
Hej
Så fandt jeg løsningen :-)
Inspireret af dette link, nederst på siden:
http://www.daniweb.com/forums/thread93386.html


Arne-inspiration
----------------
sp:
ALTER PROCEDURE [dbo].[TEST_OUTRSRET]
@outarg INTEGER OUTPUT
AS
SELECT @outarg = 123
SELECT * FROM vendors
RETURN @outarg


C-sharp-kode
-------------
public int RecievedReturnnumber(int activityID)
{
  int allReturnedNumbered = 0;
  SqlConnection connection = new SqlConnection(this.ConnectionString);
  SqlCommand command = new SqlCommand();
  command.Connection = connection;
  command.CommandType = CommandType.StoredProcedure;
  command.CommandText = "TEST_OUTRSRET";
  command.Parameters.Add("@outarg", SqlDbType.Int);
  command.Parameters["@outarg"].Direction = ParameterDirection.Output;

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

  connection.Open();
  command.ExecuteNonQuery();

  allReturnedNumbered = (int)command.Parameters["@RETURN_VALUE"].Value;

  connection.Close(); connection = null; command = null;
  return allReturnedNumbered;
}



Her overført til mit eget problem:
-----------------------------------
Stored Procedure:
ALTER PROCEDURE [dbo].[nlx_RecievedReturnnumber]
(
    @ActivityID INT,
    @iReturnedStuff bit OUTPUT
)
AS

    DECLARE @PartorderStatusID16 INT
    DECLARE @PartorderStatus16WithReturnNumber INT

SET @PartorderStatusID16 =(
SELECT COUNT(*)
FROM PartOrderStatus INNER JOIN PartOrders ON PartOrderStatus.PartOrderStatusID = PartOrders.PartOrderStatusID
WHERE ActivityID = @ActivityID AND PartOrders.PartOrderStatusID = 16
)


SET @PartorderStatus16WithReturnNumber = (
SELECT COUNT(PartVendorReturnReferenceNumber)
FROM PartOrderStatus INNER JOIN PartOrders ON PartOrderStatus.PartOrderStatusID = PartOrders.PartOrderStatusID
WHERE ActivityID = @ActivityID AND PartOrders.PartOrderStatusID = 16
)
IF (@PartorderStatus16WithReturnNumber - @PartorderStatusID16 = 0)
BEGIN
    SET @iReturnedStuff = 1
END

ELSE
BEGIN
    SET @iReturnedStuff = 0
END

RETURN @iReturnedStuff

c-sharp-koden
--------------
        public bool RecievedReturnnumber(int activityID)
        {
            SqlConnection connection = new SqlConnection(this.ConnectionString);
            SqlCommand command = new SqlCommand();
            command.Connection = connection;
            command.CommandType = CommandType.StoredProcedure;
            command.CommandText = "nlx_RecievedReturnnumber";
            command.Parameters.AddWithValue("@ActivityID", activityID);

            command.Parameters.Add("@iReturnedStuff", SqlDbType.Bit);
            command.Parameters["@iReturnedStuff"].Direction = ParameterDirection.Output;

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

            connection.Open();
            command.ExecuteNonQuery();
            bool allReturnedNumbered = Convert.ToBoolean(command.Parameters["@RETURN_VALUE"].Value);

            connection.Close(); connection = null; command = null;
            return allReturnedNumbered;
        }

Det lader til at løsenet var "@RETURN_VALUE". Jeg ved ikke om jeg har forstået ExecuteNonQuery() rigtigt; ser ud til at returnere antallet af rækker. Dvs - i dette tilfælde ikke at gøre noget "andet" end at exekverer SP. Er det en rigtig antagelse?

Jeg ved ikke om du vil ha' point?
Avatar billede arne_v Ekspert
31. juli 2008 - 23:37 #13
Det burde nu også kunne virke med en out parameter. Men med en enkelt værdi er
retur værdi vil lige så logisk.
Avatar billede arne_v Ekspert
31. juli 2008 - 23:37 #14
command.ExecuteNonQuery();

bruges til alle kald som ikke returnerer result set.
Avatar billede arne_v Ekspert
31. juli 2008 - 23:38 #15
point ? jo - hvis du mener at jeg har fortjent !
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester