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?
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.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With