web-dev-qa-db-fra.com

Passage des paramètres de sortie à la procédure stockée à l'aide de dapper en code c #

J'ai une procédure stockée dans ce format

CREATE PROCEDURE SP_MYTESTpROC
    @VAR1 VARCHAR(10),
    @VAR2 VARCHAR(20),
    @BASEID INT ,
    @NEWID INT OUTPUT
As Begin
   INSERT INTO TABLE_NAME(username, firstname)
      select @VAR1, @VAR2 
      WHERE ID = @BASEID

   SET @NEWID = SCOPE_IDENTITY() AS INT
END

J'appelle cette procédure stockée à partir du code C # à l'aide de dapper. Ma question est: comment passer le paramètre de sortie à la procédure stockée lors de l'utilisation de dapper?

30
lacoder

En recherchant simplement le fichier Test.cs , vous pouvez trouver cet exemple

    public void TestProcSupport()
    {
        var p = new DynamicParameters();
        p.Add("a", 11);
        p.Add("b", dbType: DbType.Int32, direction: ParameterDirection.Output);
        p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
        connection.Execute(@"create proc #TestProc 
                         @a int,
                             @b int output
                             as 
                             begin
                                 set @b = 999
                                 select 1111
                                 return @a
                             end");
        connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111);
        p.Get<int>("c").IsEqualTo(11);
        p.Get<int>("b").IsEqualTo(999);
    }

Donc, je suppose que votre code C # pourrait être écrit comme

    public void InsertData()
    {
        var p = new DynamicParameters();
        p.Add("VAR1", "John");
        p.Add("VAR2", "McEnroe");
        p.Add("BASEID", 1);
        p.Add("NEWID", dbType: DbType.Int32, direction: ParameterDirection.Output);
        connection.Query<int>("SP_MYTESTpROC", p, commandType: CommandType.StoredProcedure);
        int newID =  p.Get<int>("NEWID");
    }

En guise de remarque, n'utilisez pas SP comme préfixe pour votre procédure stockée. Il est réservé aux procédures définies par le système et vous pourriez vous retrouver en difficulté si Microsoft décide d'utiliser le même nom. Bien qu'improbable c'est une mauvaise pratique et pourquoi risquer?

58
Steve

Suite à la suggestion de "ath": Pour éviter la réflexion, DynamicParmers.AddDynamicParams () prend un objet anonyme, après quoi vous pouvez ajouter le paramètre de retour comme ceci ...

var param = new { A="a", B="b" };
var dynamicParameters = new DynamicParameters();
dynamicParameters.AddDynamicParams(parameters);
dynamicParameters.Add("return", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

utilisez maintenant l'objet dynamicParameters dans votre appel dapper au lieu de l'objet param anonyme.

(Vous pouvez également le faire pour un paramètre de sortie si vous préférez)

2
David Bridge

Si vous avez toujours un paramètre OUTPUT de type INTEGER nommé @id (@id = @id OUTPUT), vous pouvez créer une méthode d'extension comme celle-ci qui vous permettrait d'utiliser la syntaxe régulière Dapper en passant la chaîne sql et un objet anonymous:

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

public static int ExecuteOutputParam
            (this IDbConnection conn, string sql, object args)
        {
            // Stored procedures with output parameter require
            // dynamic params. This assumes the OUTPUT parameter in the
            // SQL is an INTEGER named @id.
            var p = new DynamicParameters();
            p.Add("id", dbType: DbType.Int32, direction: ParameterDirection.Output);

            var properties = args.GetType().GetProperties();
            foreach (var prop in properties)
            {
                var key = prop.Name;
                var value = prop.GetValue(args);

                p.Add(key, value);
            }

            conn.Execute(sql, p);

            int id = p.Get<int>("id");
            return id;
        }

Cela utilise la réflexion pour lire toutes les propriétés, mais si vous pouvez prendre cette pénalité, vous n'avez pas à chauffer le DynamicParameters pour chaque appel.

Pour les transactions, faites une méthode d'extension sur SqlTransaction en la passant à Execute comme ceci:

transaction.Connection.Execute(sql, p, transaction);
1
ath