C# – Dapper を使用して動的パラメーターを追加する

Dapper で動的パラメーターを追加する最も簡単な方法は、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)

DynamicParameters クラスを使用して、動的パラメーターを追加することもできます。特定のシナリオで最も単純なアプローチを使用できます。この記事では、さまざまなシナリオで動的パラメーターを追加する例を示します。

動的パラメータを 1 つずつ追加する

DynamicParameter.Add() を使用して、個々の動的パラメーターを一度に 1 つずつ追加できます。

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

最低限、名前と値を追加する必要があります。 Add() には、その他のオプションのパラメーターがあります。これは、パラメーターに関する追加情報を追加する場合に最も役立ちます。

既知のパラメータと動的パラメータを追加

使用しているパラメータが事前にわかっている場合は、Dapper に param を渡すことができます 各パラメーターのプロパティを持つオブジェクト。動的パラメーターも追加する必要がある場合は、DynamicParameters クラスを使用して追加し、param AddDynamicParams() メソッドを使用してオブジェクトを作成します。以下に例を示します:

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

示されているように、DynamicParameters オブジェクトを Dictionary で初期化してから、必要なパラメーターを追加できます。

ストアド プロシージャ出力パラメータの取得

DynamicParameters クラスを使用して、ストアド プロシージャの出力パラメーターを取得できます。このパラメーターを追加するときは、必ず DbType を設定し、ParameterDirection.Output を使用してください。クエリを実行した後、DynamicParameters オブジェクトから出力パラメーター値を取得できます。既知の入力パラメータ (AddDynamicParams() を使用) と出力パラメータを追加する例を次に示します:

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)

DbType パラメータを設定する必要がありますか?はい。そうしないと、間違った値を取得する可能性があります。たとえば、DbType パラメーターを DbType.Int32 に設定しない場合、出力パラメーターは 65 ではなく 2 として返されます。出力パラメーターには常に DbType を設定してください。

動的パラメーターを使用した WHERE LIKE

クエリ/パラメータを動的に構築する場合、LIKE 演算子を使用して部分一致をサポートする必要があるのは非常に一般的です。パラメータで LIKE を機能させるには、パラメータ値に % を追加します:

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

注:LIKE で使用している既知のパラメーターにも同じことが当てはまります。これは動的パラメータに固有のものではありません。

動的パラメータを使用した WHERE IN

動的パラメーターで WHERE IN を使用できます。 Dapper で必要な IN 構文を使用します (括弧で囲みません):

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

動的オブジェクトへの結果のマッピング

真にアドホックなクエリを実行している場合、結果をマップするクラスがなく、不要な場合があります。この場合、マッピング先の型 (つまり、Query()) を指定する代わりに、非ジェネリックな Query() メソッドを使用します。これは IEnumerable:

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