Pasar los parámetros de salida al procedimiento almacenado usando dapper en el código c #

c# dapper sql sql-server stored-procedures

Pregunta

Tengo un procedimiento almacenado en este formato

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

Estoy llamando a este procedimiento almacenado desde el código C # usando dapper. Mi pregunta es: ¿cómo paso el parámetro de salida al procedimiento almacenado mientras uso dapper?

Respuesta aceptada

Simplemente buscando en el archivo Test.cs podría encontrar este ejemplo

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

Entonces, supongo que su código C # podría escribirse como

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

Como nota al margen, no use SP como prefijo para su procedimiento almacenado. Está reservado para los procedimientos definidos por el sistema y usted podría encontrarse en problemas si Microsoft decide usar el mismo nombre. Aunque improbable, es una mala práctica y ¿por qué arriesgarse?


Respuesta popular

Si siempre tiene un parámetro OUTPUT de tipo INTEGER llamado @id ( @id = @id OUTPUT ), puede crear un método de extensión como este que le permita usar la sintaxis Dapper regular que pasa la cadena SQL y un objeto 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;
        }

Esto utiliza la reflexión para leer todas las propiedades, pero si puede tomar esa penalización, no tiene que DynamicParameters los DynamicParameters para cada llamada.

Para transacciones, haga un método de extensión en SqlTransaction pasándolo a Execute de la siguiente manera:

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


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué