¿Hay alguna manera de llamar a un procedimiento almacenado con Dapper?

205

Estoy muy impresionado con los resultados de Dapper Micro ORM para stackoverflow.com. Lo estoy considerando para mi nuevo proyecto y me preocupa que algunas veces mi proyecto requiera tener un procedimiento almacenado y haya buscado mucho en la web pero no haya encontrado nada con el procedimiento almacenado. Entonces, ¿hay alguna manera de hacer que Dapper funcione con un procedimiento almacenado?

Avíseme si es posible; de ​​lo contrario, tengo que extenderlo en mi camino.

Jalpesh Vadgama
fuente
Vea mis detalles, responda aquí stackoverflow.com/questions/5957774/…
Majedur Rahaman el

Respuestas:

356

En el caso simple puedes hacer:

var user = cnn.Query<User>("spGetUser", new {Id = 1}, 
        commandType: CommandType.StoredProcedure).First();

Si quieres algo más elegante, puedes hacer:

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

 cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure); 

 int b = p.Get<int>("@b");
 int c = p.Get<int>("@c"); 

Además, puede usar exec en un lote, pero eso es más torpe.

Sam Azafrán
fuente
1
El parámetro con la dirección de ReturnValue debe definirse primero, ¿verdad?
Endy Tjahjono
3
@Sam Saffron ¿Cuál es la diferencia entre .Output y .ReturnVlaue?
Timeless
Sam, ¿esto permite conjuntos de resultados de SPROCs?
Brad
2
Obtuve un escenario en el que tomaré el conjunto de resultados de la consulta y el valor del parámetro de salida en un procedimiento. Si uso, cnn.Query<MyType>¿cómo puedo obtener el valor del parámetro de salida del proceso?
Murali Murugesan
La segunda solución (elegante) también es útil para cuando necesita pasar un valor nulo para uno o más parámetros de procedimientos almacenados.
Ricardo Sánchez
13

Creo que la respuesta depende de las características de los procedimientos almacenados que necesite usar.

Los procedimientos almacenados que devuelven un conjunto de resultados se pueden ejecutar utilizando Query; los procedimientos almacenados que no devuelven un conjunto de resultados se pueden ejecutar usando Execute, en ambos casos (usando EXEC <procname>) como el comando SQL (más parámetros de entrada según sea necesario). Consulte la documentación para más detalles.

A partir de la revisión 2d128ccdc9a2 , no parece haber soporte nativo para los OUTPUTparámetros; podría agregar esto, o alternativamente construir un Querycomando más complejo que declarara variables TSQL, ejecutó los OUTPUTparámetros de recolección de SP en las variables locales y finalmente los devolvió en un conjunto de resultados:

DECLARE @output int

EXEC <some stored proc> @i = @output OUTPUT

SELECT @output AS output1
Ed Harper
fuente
17
Acabo de agregar soporte para parámetros de salida ahora, vea mi último registro
Sam Saffron
66
@Sam: ¡eso es lo que yo llamo servicio!
Ed Harper
6

Aquí hay un código para obtener el valor devuelto del procedimiento Store

Procedimiento almacenado:

alter proc [dbo].[UserlogincheckMVC]    
@username nvarchar(max),    
@password nvarchar(max)
as    
begin    
    if exists(select Username from Adminlogin where Username =@username and Password=@password)    
        begin        
            return 1  
        end    
    else    
        begin     
            return 0  
        end    
end 

Código:

var parameters = new DynamicParameters();
string pass = EncrytDecry.Encrypt(objUL.Password);
conx.Open();
parameters.Add("@username", objUL.Username);
parameters.Add("@password", pass);
parameters.Add("@RESULT", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
var RS = conx.Execute("UserlogincheckMVC", parameters, null, null, commandType: CommandType.StoredProcedure);
int result = parameters.Get<int>("@RESULT");
Saineshwar
fuente
2

Lo mismo de arriba, un poco más detallado

Usando .Net Core

Controlador

public class TestController : Controller
{
    private string connectionString;

    public IDbConnection Connection
    {
        get { return new SqlConnection(connectionString); }
    }

    public TestController()
    {
        connectionString = @"Data Source=OCIUZWORKSPC;Initial Catalog=SocialStoriesDB;Integrated Security=True";
    }

    public JsonResult GetEventCategory(string q)
    {
        using (IDbConnection dbConnection = Connection)
        {
            var categories = dbConnection.Query<ResultTokenInput>("GetEventCategories", new { keyword = q },
    commandType: CommandType.StoredProcedure).FirstOrDefault();

            return Json(categories);
        }
    }

    public class ResultTokenInput
    {
        public int ID { get; set; }
        public string name { get; set; }            
    }
}

Procedimiento almacenado (relación padre-hijo)

create PROCEDURE GetEventCategories
@keyword as nvarchar(100)
AS
    BEGIN

    WITH CTE(Id, Name, IdHierarchy,parentId) AS
    (
      SELECT 
        e.EventCategoryID as Id, cast(e.Title as varchar(max)) as Name,
        cast(cast(e.EventCategoryID as char(5)) as varchar(max)) IdHierarchy,ParentID
      FROM 
        EventCategory e  where e.Title like '%'+@keyword+'%'
     -- WHERE 
      --  parentid = @parentid

      UNION ALL

      SELECT 
        p.EventCategoryID as Id, cast(p.Title + '>>' + c.name as varchar(max)) as Name,
        c.IdHierarchy + cast(p.EventCategoryID as char(5)),p.ParentID
      FROM 
        EventCategory p 
      JOIN  CTE c ON c.Id = p.parentid

        where p.Title like '%'+@keyword+'%'
    )
    SELECT 
      * 
    FROM 
      CTE
    ORDER BY 
      IdHierarchy

Referencias en caso

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using SocialStoriesCore.Data;
using Microsoft.EntityFrameworkCore;
using Dapper;
using System.Data;
using System.Data.SqlClient;
Arun Prasad ES
fuente
¿Por qué usar Microsoft.EntityFrameworkCore? ¿Solo usando Dapper en DAL ?
PreguntonCojoneroCabrón
@ PreguntonCojoneroCabrón No es necesario, solo pegué todo
Arun Prasad ES
¿Filas de muestra para EventCategory?
Kiquenet
@ArunPrasadES al punto PreguntonCojoneroCabrón, limpie y elimine el código innecesario ya que confunde a las personas que intentan resolver un problema. Hay características en Visual Studio y Resharper que hacen esta limpieza de usos por usted.
Cubículo.Jockey
1

Con retorno múltiple y parámetro múltiple

string ConnectionString = CommonFunctions.GetConnectionString();
using (IDbConnection conn = new SqlConnection(ConnectionString))
{
    IEnumerable<dynamic> results = conn.Query(sql: "ProductSearch", 
        param: new { CategoryID = 1, SubCategoryID="", PageNumber=1 }, 
        commandType: CommandType.StoredProcedure);.  // single result

    var reader = conn.QueryMultiple("ProductSearch", 
        param: new { CategoryID = 1, SubCategoryID = "", PageNumber = 1 }, 
        commandType: CommandType.StoredProcedure); // multiple result

    var userdetails = reader.Read<dynamic>().ToList(); // instead of dynamic, you can use your objects
    var salarydetails = reader.Read<dynamic>().ToList();
}

public static string GetConnectionString()
{
    // Put the name the Sqlconnection from WebConfig..
    return ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
}
Arun Prasad ES
fuente
ProductSearch muestra ? devuelve 2 cursores?
PreguntonCojoneroCabrón
0
public static IEnumerable<T> ExecuteProcedure<T>(this SqlConnection connection,
    string storedProcedure, object parameters = null,
    int commandTimeout = 180) 
    {
        try
        {
            if (connection.State != ConnectionState.Open)
            {
                connection.Close();
                connection.Open();
            }

            if (parameters != null)
            {
                return connection.Query<T>(storedProcedure, parameters,
                    commandType: CommandType.StoredProcedure, commandTimeout: commandTimeout);
            }
            else
            {
                return connection.Query<T>(storedProcedure,
                    commandType: CommandType.StoredProcedure, commandTimeout: commandTimeout);
            }
        }
        catch (Exception ex)
        {
            connection.Close();
            throw ex;
        }
        finally
        {
            connection.Close();
        }

    }
}

var data = db.Connect.ExecuteProcedure<PictureModel>("GetPagePicturesById",
    new
    {
        PageId = pageId,
        LangId = languageId,
        PictureTypeId = pictureTypeId
    }).ToList();
Hakan YILMAZ
fuente