Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative way to get output parameter from stored procedure

Tags:

dapper

I love using Dapper for my ORM needs but I know there must be a better way to insert/update my sql server database using a stored procedure and strongly typed Lists.

For example:

I have a class Song:

    public class Song
{
    public int Id { get; set; }
    public string title { get; set; }
    public string genre { get; set; }
}

and somebody submits a List of songs:

 List<Song> songs = new List<Song> { 
            new Song { Id = 1, title = "Song 1" , genre="rock"}, 
            new Song { Id = 2, title = "Song 2" , genre="disco"}};

I want to update the database using my stored procedure which either inserts the new song or updates it if the song already exists. My stored procedure has two output parameters: @success_added int = 0 and @success_updated int = 0

my sproc is as follows:

ALTER PROCEDURE [dbo].[UpdateSong] 
@Id int = 0, 
@title varchar(25) = NULL,
@genre varchar(25) = NULL,
@success_updated bit = 0 OUTPUT,
@success_added bit = 0 OUTPUT
AS
IF NOT EXISTS (SELECT Id  FROM Songs WHERE Id = @Id)
    BEGIN
        INSERT INTO Songs
        (
        -- Id created by db
        title,
        genre
        ) 
        VALUES
        (
        @title, 
        @genre
        )
        SELECT @Success_Added = 1, @Success_Updated = 0
    END
ELSE -- song already exists
    BEGIN
        UPDATE Songs  
        SET
        title = @title,
        @genre = @genre
        WHERE Id = @Id
        SELECT @Success_Added = 0, @Success_Updated = 1
    END
RETURN

I know this works:

dbConn.Open();
DynamicParameters p = new DynamicParameters();
foreach (var song in songs)
  {
    p.Add("@Id", song.Id);
    p.Add("@title", song.title);
    p.Add("@genre", song.genre);
    p.Add("@success_updated", dbType: DbType.Boolean, direction: ParameterDirection.Output);
    p.Add("@success_added", dbType: DbType.Boolean, direction: ParameterDirection.Output);
    dbConn.Execute("Test_UpdateSong", p, commandType: CommandType.StoredProcedure);
    Console.WriteLine("@success_added: " + p.Get<Boolean>("@success_added"));
    Console.WriteLine("@success_updated: " + p.Get<Boolean>("@success_updated"));
  }
dbConn.Close();

But that requires manually converting each Song property to a anonymous type DynamicParameter. I'd rather simply do this:

dbConn.Open();
foreach (var song in songs)
  {
    var updateResult = dbConn.Query<dynamic>("Test_UpdateSong", song, commandType: CommandType.StoredProcedure);
  }
dbConn.Close();

Which also works. But, now how do I get my output parameters?

like image 373
tommy Avatar asked Feb 22 '15 00:02

tommy


People also ask

Can stored procedure have output parameter?

The Output Parameters in Stored Procedures are used to return some value or values. A Stored Procedure can have any number of output parameters. The simple logic is this — If you want to return 1 value then use 1 output parameter, for returning 5 values use 5 output parameters, for 10 use 10, and so on.

How can get stored procedure output in SQL Server?

The easy way is to right-click on the procedure in Sql Server Management Studio (SSMS), select 'Execute stored procedure..." and add values for the input parameters as prompted. SSMS will then generate the code to run the procedure in a new query window, and execute it for you.


1 Answers

As I stated originally, I didn't want to have to manually convert each class property to a Dapper dynamic parameter. This is critical because if I create a generic method, I may not know which class is being passed into the method and thus which properties to pass to convert to dynamic parameters. Taking @Metro Smurfs advice (when all else fails read the directions), I looked into the Dapper test class and found a solution that works for me:

DynamicParameters p = new DynamicParameters(song);

by adding the song object to the DynamicParameters constructor, a DynamicParameters template is created which will automatically convert all properties to parameters. Then I can simply add my two output parameters and execute the sproc:

p.Add("@success_updated", dbType: DbType.Boolean, direction: ParameterDirection.Output);
p.Add("@success_added", dbType: DbType.Boolean, direction: ParameterDirection.Output);
dbConn.Execute("Test_UpdateSong", p, commandType: CommandType.StoredProcedure);
// get my output parameters...
var success_added = p.Get<bool>("@success_Added");
var success_added = p.Get<bool>("@success_Updated");

and I'm good to go! Thanks to @Nick and @Metro Smurf for the suggestions!

like image 159
tommy Avatar answered Sep 19 '22 15:09

tommy