C#:agregar parámetros dinámicos con Dapper

C#:agregar parámetros dinámicos con Dapper

La forma más sencilla de agregar parámetros dinámicos con Dapper es pasar Dictionary:

//Built dynamically somewhere
var query = "SELECT * FROM Movies WHERE Name=@Name";
var parameters = new Dictionary<string, object>()
{
	["Name"] = "The Matrix"
};

//Executing the query with dynamic parameters
using (var con = new SqlConnection(connectionString))
{
	var results = con.Query<Movie>(query, parameters);
	return results;
}
Code language: C# (cs)

También puede agregar parámetros dinámicos mediante la clase DynamicParameters. Puede usar el enfoque que sea más simple en el escenario dado. En este artículo, mostraré ejemplos de cómo agregar parámetros dinámicos en diferentes escenarios.

Añadir parámetros dinámicos de uno en uno

Puede agregar parámetros dinámicos individuales de uno en uno usando DynamicParameter.Add().

//Built dynamically somewhere
var query = "SELECT * FROM Movies WHERE Id=@Id";
var paramName = "@Id"; //works without the @ too
var paramValue = 3;

//Dynamic parameters added individually
using (var con = new SqlConnection(connectionString))
{
	var dynamicParameters = new DynamicParameters();
	dynamicParameters.Add(paramName, paramValue);

	var results = con.Query<Movie>(query, dynamicParameters);
	return results;
}
Code language: C# (cs)

Como mínimo, debe agregar el nombre y el valor. Add() tiene otros parámetros opcionales. Esto es principalmente útil cuando agrega información adicional sobre los parámetros.

Añadir parámetros conocidos y parámetros dinámicos

Cuando sepa qué parámetros está usando con anticipación, puede pasarle a Dapper un param objeto con propiedades para cada parámetro. Si también necesita agregar parámetros dinámicos, agréguelos con la clase DynamicParameters y agregue el param objeto mediante el método AddDynamicParams(). He aquí un ejemplo:

//Built dynamically somewhere
var query = "SELECT * FROM Movies WHERE Name=@Name AND YearOfRelease=@Year";
var parameters = new Dictionary<string, object>()
{
	["Year"] = 1999
};

//Using hardcoded (known) parameters  + dynamic parameters
using (var con = new SqlConnection(connectionString))
{
	var dynamicParameters = new DynamicParameters(parameters);

	dynamicParameters.AddDynamicParams(new { name = "The Matrix" });
		
	var results = con.Query<Movie>(query, dynamicParameters);
	return results;
}
Code language: C# (cs)

Como se muestra, puede inicializar el objeto DynamicParameters con Dictionary y luego agregar cualquier parámetro adicional que necesite.

Obtener un parámetro de salida de proceso almacenado

Puede usar la clase DynamicParameters para obtener un parámetro de salida de proceso almacenado. Cuando agregue este parámetro, asegúrese de configurar DbType y usar ParameterDirection.Output. Después de ejecutar la consulta, puede obtener el valor del parámetro de salida del objeto DynamicParameters. Este es un ejemplo de cómo agregar parámetros de entrada conocidos (con AddDynamicParams()) y un parámetro de salida:

var year = 2022;

using (var con = new SqlConnection(connectionString))
{
	var dynamicParameters = new DynamicParameters();
	dynamicParameters.AddDynamicParams(new { year });
	dynamicParameters.Add("count", DbType.Int32, direction: ParameterDirection.Output);

	var results = con.Query<Movie>("spGetMoviesForYear", dynamicParameters, commandType: CommandType.StoredProcedure);

	var count = dynamicParameters.Get<int>("count");
	Console.WriteLine($"Got {count} records");

	return results;
}
Code language: C# (cs)

¿Necesita configurar el parámetro DbType? Sí. De lo contrario, obtendrá potencialmente el valor incorrecto. Por ejemplo, si no establezco el parámetro DbType en DbType.Int32, el parámetro de salida vuelve a ser 2 en lugar de 65. Establezca siempre DbType para los parámetros de salida.

WHERE LIKE con un parámetro dinámico

Cuando crea consultas/parámetros dinámicamente, es bastante común que necesite admitir coincidencias parciales mediante el operador LIKE. Para hacer que LIKE funcione con un parámetro, agregue % al valor del parámetro:

//Built dynamically somewhere
var movieNameLike = "Matrix";
var query = "SELECT * FROM Movies WHERE Name LIKE @Name";
var parameters = new Dictionary<string, object>()
{
	["Name"] = $"%{movieNameLike}%"
};

//Using the dynamic parameters like usual
using (var con = new SqlConnection(connectionString))
{
	var results = con.Query<Movie>(query, parameters);
	return results;
}
Code language: C# (cs)

Nota:lo mismo se aplica a los parámetros conocidos que usa con LIKE. Esto no es específico de los parámetros dinámicos.

WHERE IN con un parámetro dinámico

Puede usar WHERE IN con parámetros dinámicos. Use la sintaxis IN requerida por Dapper (sin paréntesis):

//Built dynamically somewhere
var query = "SELECT * FROM Movies WHERE Id IN @Ids";
var parameters = new Dictionary<string, object>()
{
	["Ids"] = new List<int>()
	{
		17, 18, 19
	}
};

//Using the dynamic parameters like usual
using (var con = new SqlConnection(connectionString))
{
	var results = con.Query<Movie>(query, parameters);
	return results;
}
Code language: C# (cs)

Mapeo de resultados a un objeto dinámico

Si está ejecutando consultas verdaderamente ad hoc, es posible que no tenga una clase a la que asignar los resultados y que no desee una. En este caso, en lugar de especificar un tipo para mapear (es decir, Query()), use el método Query() no genérico, que devuelve IEnumerable:

using (var con = new SqlConnection(connectionString))
{
	IEnumerable<dynamic> results = con.Query(query, parameters);
	return results;
}
Code language: C# (cs)