从存储过程中检索返回值

时间:2016-07-13 01:07:06

标签: c# stored-procedures sql-server-2012 table-valued-parameters

我编写了一个表值参数存储过程,它返回插入的Id。如果我从SSMS内部的查询运行它,它可以正常工作并返回值。

当我从代码调用该过程时,它会运行并插入数据但不会设置我添加的返回参数并将其标记为返回参数。

我在这里做错了什么?

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,
        MeetingLocationId=@MeetingLocationId,
        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#代码:

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

4 个答案:

答案 0 :(得分:2)

该输出值不会从ExecuteNonQuery返回。尝试创建对返回参数的引用,如下所示:

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

command.Parameters.Add(returnParameter);

然后执行后,

var myReturnedValue = returnParameter.Value;

你也可以改变

RETURN @MeetingId;

SELECT @MeetingId;

然后使用

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

答案 1 :(得分:0)

您需要使用ExecuteScalar来捕获返回的值,或使用output参数。

这篇文章回答了一个类似的问题。 Calling stored procedure with return value

答案 2 :(得分:0)

使用ADO.NET从存储过程中获取返回值有多种方法。

我的例子是我以前用过的通用方法。您可以使用存储过程或文本传递SQL命令。

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

答案 3 :(得分:0)

我刚刚注意到你没有在你的SP定义中声明你的@MeetingId参数(你在身体中做了但我不认为可以使用它)。

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

然后在你的代码中你可以用它来抓住它:

command.Parameters["@MeetingId"].Value