0

Ich habe eine gespeicherte Prozedur geschrieben, die den Tabellenwert angibt. Sie gibt die ID zurück, die eingefügt wurde. Wenn ich es von einer Abfrage in SSMS aus führe, funktioniert es und gibt den Wert korrekt zurück.Abrufen von Rückgabewert von gespeicherter Prozedur

Wenn ich die Prozedur aus Code aufrufen, wird ausgeführt, und fügt die Daten ein, aber nicht den Rückgabeparameter, den ich hinzugefügt und als Rückgabeparameter markiert habe.

Was mache ich hier falsch?

SP:

ALTER PROCEDURE [dbo].[InsertUpdateMeeting] 
    -- Add the parameters for the stored procedure here 
    @Meeting MeetingsTableType READONLY, 
    @Area AreasTableType READONLY, 
    @MeetingLocation MeetingLocationsTableType READONLY 

AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 
    -- Insert statements for procedure here 
    DECLARE @MeetingId int = 0; 
    DECLARE @AreaId int; 
    DECLARE @MeetingLocationId int; 

    SELECT TOP 1 @MeetingId=m.MeetingId FROM @Meeting AS m; 
    SELECT TOP 1 @MeetingLocationId = ml.MeetingLocationId FROM @MeetingLocation AS ml; 
    SELECT TOP 1 @AreaId = a.AreaId FROM @Area AS a; 

    UPDATE Areas SET 
     Hotline=areaParam.Hotline, 
     Name=areaParam.Name 
    FROM Areas INNER JOIN @Area AS areaParam 
    ON Areas.AreaId=areaParam.AreaId; 
    IF(@@ROWCOUNT=0) 
     BEGIN; 
      INSERT INTO Areas 
       (Hotline,Name) 
      SELECT areaParam.Hotline,areaParam.Name FROM @Area AS areaParam; 
      SET @AreaId=SCOPE_IDENTITY(); 
     END; 
    UPDATE MeetingLocations SET 
     Address1=ml.Address1, 
     Address2=ml.Address2, 
     Address3=ml.Address3, 
     City=ml.City, 
     [State]=ml.[State], 
     Zip=ml.Zip, 
     ClubName=ml.ClubName, 
     ClubDescription=ml.ClubDescription, 
     MapLink=ml.MapLink 
    FROM MeetingLocations INNER JOIN @MeetingLocation AS ml 
    ON MeetingLocations.MeetingLocationId=ml.MeetingLocationId; 
    IF(@@ROWCOUNT=0) 
     BEGIN; 
      INSERT INTO MeetingLocations 
       (Address1,Address2,Address3,City,[State],Zip,ClubName,ClubDescription,MapLink) 
      SELECT ml.Address1,ml.Address2,ml.Address3,ml.City,ml.[State],ml.Zip,ml.ClubName,ml.ClubDescription,ml.MapLink 
      FROM @MeetingLocation AS ml; 
      SET @MeetingLocationId=SCOPE_IDENTITY(); 
     END; 
    UPDATE Meetings SET 
     AreaId = @AreaId, 
     [email protected], 
     Name = meetingParam.Name 
    FROM Meetings INNER JOIN @Meeting AS meetingParam 
    ON Meetings.MeetingId=meetingParam.MeetingId; 
    IF(@@ROWCOUNT=0) 
     BEGIN; 
      INSERT INTO Meetings 
       (MeetingLocationId,AreaId,Name) 
      SELECT @MeetingLocationId,@AreaId,meetingParam.Name FROM @Meeting AS meetingParam; 
      SET @MeetingId=SCOPE_IDENTITY(); 
     END; 
    RETURN @MeetingId; 
END 

C# -Code:

...create tables... 
var meetingLocationParam = new SqlParameter("@MeetingLocation", meetingLocationTable); 
meetingLocationParam.SqlDbType = SqlDbType.Structured; 
meetingLocationParam.TypeName = "MeetingLocationsTableType"; 
var meetingParam = new SqlParameter("@Meeting", meetingTable); 
meetingParam.SqlDbType = SqlDbType.Structured; 
meetingParam.TypeName = "MeetingsTableType"; 
var areaParam = new SqlParameter("@Area", areaTable); 
areaParam.TypeName = "AreasTableType"; 
areaParam.SqlDbType = SqlDbType.Structured; 
using (var connection = new SqlConnection(conn.ConnectionString)) 
using (var command = new SqlCommand()) 
{ 
    connection.Open(); 
    command.Connection = connection; 
    command.CommandText = "EXEC dbo.InsertUpdateMeeting"; 
    command.Parameters.AddRange(new SqlParameter[] 
    {meetingParam, areaParam, meetingLocationParam, new SqlParameter() 
    { 
     Value=0, 
     Direction=ParameterDirection.ReturnValue, 
     SqlDbType=SqlDbType.Int, 
     ParameterName="@MeetingId" 
    } }); 
    var otherRet = command.ExecuteNonQuery(); 

    //Assert.IsTrue(ret > 0); 
} 
+0

int retunvalue = (int) Command.Parameters [ "@ MeetingID"] Wert;. wird dies helfen, den Wert nach dem Ausführen des Befehls abzurufen? – Hybridzz

+0

es hat einen Wert von 0. also nein, leider. Ich muss etwas Offensichtliches vermissen, weil das einfach sein sollte. –

+0

Das otherRet ist normalerweise die betroffenen Zeilen und nicht Ihre @MeetingId. Überprüfen Sie einfach Ihre 'command.Parameters [" @ MeetingId "]. Value'. – Zach

Antwort

2

Dieser Ausgabewert wird nicht von ExecuteNonQuery zurückgegeben. Versuchen Sie, einen Verweis auf Ihre Rückgabeparameter wie folgt zu erstellen:

var returnParameter = new SqlParameter[] 
{meetingParam, areaParam, meetingLocationParam, new SqlParameter() 
{ 
    Value=0, 
    Direction=ParameterDirection.ReturnValue, 
    SqlDbType=SqlDbType.Int, 
    ParameterName="@MeetingId" 
} } 

command.Parameters.Add(returnParameter); 

Dann, nach der Ausführung

var myReturnedValue = returnParameter.Value; 

Sie auch

RETURN @MeetingId; 

zu

SELECT @MeetingId; 
ändern könnte

und verwendet dann

var myReturnedValue = (int)command.ExecuteScalar(); 
+0

ExecuteNonQuery gibt -1 zurück, aber der Verweis auf den Rückgabeparameter i add hat den Wert 0, was definitiv nicht die ID ist, die von meinem SP eingefügt oder zurückgegeben wurde. –

+0

Ich sehe es nicht in Ihrem Code. Wo überprüfst du den Wert des Parameters? –

+1

Es kann einfacher sein, nur den Wert auszuwählen, anstatt ihn zurückzugeben, und dann 'ExecuteScalar' zu verwenden, um ihn abzurufen. –

0

Sie müssen entweder ExecuteScalar verwenden, um den zurückgegebenen Wert catpure oder die output Parameter verwenden.

Eine ähnliche Frage wurde in diesem Post beantwortet. Calling stored procedure with return value

+0

Vielen Dank für den Link, leider habe ich es gesehen und das hat mein Problem nicht gelöst. Der Wert des Rückgabeparameters ist 0. Das ist nicht das, was der SP zurückgibt. Ich werde versuchen, den Ausgabeparameter zu verwenden. –

0

Es gibt mit ADO.NET einen Rückgabewert aus einer gespeicherten Prozedur mehr Möglichkeiten zu bekommen.

Mein Beispiel sind generische Methoden, die ich zuvor verwendet habe. Sie können einen SQL-Befehl mit einer gespeicherten Prozedur oder einem Text übergeben.

  1. SqlAdapter

    /// <summary> 
    /// Returns a DataSet given an Sql Command 
    /// </summary> 
    /// <param name="cmd">The SqlCommand object</param> 
    /// <returns>DataSet</returns> 
    public static DataSet GetDataSet(SqlCommand cmd) 
    { 
        using (SqlConnection con = DbConnect()) // DbConnect() returns SqlConnection instance 
        { 
         DataSet ds = new DataSet(); 
         SqlDataAdapter da = new SqlDataAdapter(cmd); 
         cmd.Connection = con; 
         da.Fill(ds, "my_dataset"); 
    
         return ds; 
        } 
    } 
    
  2. ExecuteScalar

    /// <summary> 
    /// Returns a single value from the database given an Sql Command object 
    /// </summary> 
    /// <param name="cmd">The Sql Command object</param> 
    /// <returns>string</returns> 
    public static string GetSingleFromDatabase(SqlCommand cmd) 
    { 
        using (SqlConnection con = DbConnect()) // DbConnect() returns SqlConnection instance 
        { 
         cmd.Connection = con; 
    
         try 
         { 
          object returnedValue = cmd.ExecuteScalar(); 
          if (returnedValue != null) 
          { 
           return returnedValue.ToString(); 
          } 
          else 
           return ""; 
         } 
         catch (Exception) 
         { 
          throw; 
         } 
        } 
    } 
    
+0

Der von ExecuteScalar zurückgegebene Wert ist null und der Wert von returnParameter ist 0. –

+0

@MichaelBillingham Dann müssen Sie überprüfen und überprüfen, ob Ihre gespeicherte Prozedur tatsächlich einen Wert zurückgibt, der die gleichen Parameter verwendet, die Sie als null zurückgegeben haben. Überprüfen Sie es in SQL Server. –

0

ich gerade bemerkt, dass Sie nicht Ihren @MeetingId Parameter in Ihrer SP Definition erklären (Sie im Körper haben, aber Ich glaube nicht, dass das benutzt werden kann).

ALTER PROCEDURE [dbo].[InsertUpdateMeeting] 
    -- Add the parameters for the stored procedure here 
    @Meeting MeetingsTableType READONLY, 
    @Area AreasTableType READONLY, 
    @MeetingLocation MeetingLocationsTableType READONLY, 
    @MeetingId <datatype> OUTPUT -- ADD THIS 
AS 

Dann in Ihrem Code können Sie es mit dieser greifen:

command.Parameters["@MeetingId"].Value 
Verwandte Themen