C# – Aggiunta di parametri dinamici con Dapper

C# – Aggiunta di parametri dinamici con Dapper

Il modo più semplice per aggiungere parametri dinamici con Dapper è passare in 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)

Puoi anche aggiungere un parametro dinamico usando la classe DynamicParameters. È possibile utilizzare l'approccio più semplice nello scenario specificato. In questo articolo mostrerò esempi di aggiunta di parametri dinamici in diversi scenari.

Aggiungi i parametri dinamici uno alla volta

Puoi aggiungere singoli parametri dinamici uno alla volta utilizzando 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)

Come minimo, devi aggiungere il nome e il valore. Add() ha altri parametri opzionali. Questo è utile soprattutto quando aggiungi ulteriori informazioni sui parametri.

Aggiungi parametri noti e parametri dinamici

Quando sai quali parametri stai utilizzando in anticipo, puoi passare a Dapper un param oggetto con proprietà per ogni parametro. Se devi aggiungere anche parametri dinamici, aggiungili con la classe DynamicParameters e aggiungi il param oggetto utilizzando il metodo AddDynamicParams(). Ecco un esempio:

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

Come mostrato, puoi inizializzare l'oggetto DynamicParameters con Dictionary, quindi aggiungere eventuali parametri aggiuntivi di cui hai bisogno.

Ottenere un parametro di output proc memorizzato

È possibile utilizzare la classe DynamicParameters per ottenere un parametro di output proc archiviato. Quando aggiungi questo parametro, assicurati di impostare DbType e di utilizzare ParameterDirection.Output. Dopo aver eseguito la query, è possibile ottenere il valore del parametro di output dall'oggetto DynamicParameters. Ecco un esempio di aggiunta di parametri di input noti (con AddDynamicParams()) e un parametro di output:

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)

Devi impostare il parametro DbType? Sì. Altrimenti otterrà potenzialmente il valore sbagliato. Ad esempio, se non imposto il parametro DbType su DbType.Int32, il parametro di output torna come 2 invece di 65. Impostare sempre il DbType per i parametri di output.

WHERE LIKE con un parametro dinamico

Quando crei query/parametri in modo dinamico, è abbastanza comune dover supportare corrispondenze parziali utilizzando l'operatore LIKE. Per fare in modo che LIKE funzioni con un parametro, aggiungi % al valore del parametro:

//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 stesso vale per i parametri noti che stai utilizzando con LIKE. Questo non è specifico per i parametri dinamici.

WHERE IN con un parametro dinamico

Puoi usare WHERE IN con parametri dinamici. Usa la sintassi IN richiesta da Dapper (senza parentesi racchiuse):

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

Mappatura dei risultati su un oggetto dinamico

Se stai eseguendo query veramente ad hoc, potresti non avere una classe su cui mappare i risultati e potresti non volerne una. In questo caso, invece di specificare un tipo a cui eseguire il mapping (ad esempio Query()), utilizzare il metodo Query() non generico, che restituisce IEnumerable:

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