C# – Dapper を使用した基本的な SQL クエリの実行

Dapper を使用して基本的な SELECT クエリを実行する例を次に示します。

using System.Data.SqlClient;
using Dapper;

public IEnumerable<Movie> GetAllMovies()
{
	using (var con = new SqlConnection(connectionString))
	{
		return con.Query<Movie>("SELECT * FROM Movies");
	}
}
Code language: C# (cs)

Dapper は、マッピング パラメータやクエリ結果など、SQL クエリの実行に関連する反復コードを抽象化します。これは構成なしで行われます (リフレクションを使用してマッピングされます)。

この記事では、クエリ パラメーターの追加やレコードの挿入など、一般的なシナリオで Dapper を使用する例をさらに示します。

注:まだ行っていない場合は、Dapper nuget パッケージを追加してください .

クエリ パラメータの追加

Dapper でクエリ パラメータを追加するには、param のオブジェクトを渡します 引数:

public IEnumerable<Movie> GetMoviesForYear(int year)
{
	using (var con = new SqlConnection(connectionString))
	{
		return con.Query<Movie>("SELECT * FROM Movies WHERE YearOfRelease=@year", 
			param: new { year });
	}
}
Code language: C# (cs)

匿名型を含む任意のオブジェクトを渡すことができます (上記を参照)。 Dapper は param からプロパティをマッピングしようとします クエリ内のパラメーター プレースホルダー (つまり、「@year」) に反対します。

ストアド プロシージャの呼び出し

次のストアド プロシージャを呼び出すとします。

CREATE PROCEDURE spGetMoviesForYear
	@year int
AS
BEGIN
	SELECT * FROM Movies WHERE YearOfRelease=@year
END
Code language: plaintext (plaintext)

このストアド プロシージャを Dapper で呼び出す方法の例を次に示します。

public IEnumerable<Movie> GetMoviesForYearSP(int year)
{
	using (var con = new SqlConnection(connectionString))
	{
		return con.Query<Movie>("dbo.spGetMoviesForYear", 
			param: new { year }, 
			commandType: System.Data.CommandType.StoredProcedure);
	}
}
Code language: C# (cs)

ストアド プロシージャ名と任意のパラメーターを指定し、commandType 引数を CommandType.StoredProcedure に設定します。

レコードの挿入

以下は、単一の Movie レコードを挿入する例です:

private const string INSERT_SQL =
@"INSERT INTO [Movies]
	([Name]
	,[YearOfRelease]
	,[Description]
	,[Director]
	,[BoxOfficeRevenue])	   
VALUES
	(@Name,
	@YearOfRelease,
	@Description,
	@Director,
	@BoxOfficeRevenue)";

public void Insert(Movie movie)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute(INSERT_SQL, param: movie);
	}
}
Code language: C# (cs)

INSERT ステートメントは他の SQL ステートメントに比べて非常に冗長であるため、挿入のコードは少し面倒です。 CRUD 操作を抽象化して SQL を書かなくて済むようにする Dapper 用の拡張ライブラリがありますが、私は個人的にはそれらを使用しません。 Dapper の利点の 1 つは、記述した SQL クエリを実行することです。そのため、驚くようなことはありません。

param の映画オブジェクトを渡すことができる パラメータ リストを入力する必要がないため、引数が役立ちます。 INSERT ステートメントを記述するには、通常 Script Table as> INSERT INTO を使用します。 SSMS で開始点スクリプトを作成するか、メタデータを使用してクエリを生成します。

挿入された ID 値の取得

ID 列を持つテーブルにレコードを挿入すると、クエリに OUTPUT INSERTED.Id を追加することで、挿入された ID 値を取得できます。 ExecuteScalar() を使用して、単一の戻り値を取得します:

private const string INSERT_OUTPUT_ID_SQL =
@"INSERT INTO [Movies]
	([Name]
	,[YearOfRelease]
	,[Description]
	,[Director]
	,[BoxOfficeRevenue])
OUTPUT INSERTED.Id
VALUES
	(@Name,
	@YearOfRelease,
	@Description,
	@Director,
	@BoxOfficeRevenue)";
	
public int InsertAndReturnId(Movie movie)
{
	using (var con = new SqlConnection(connectionString))
	{
		return con.ExecuteScalar<int>(INSERT_OUTPUT_ID_SQL, param: movie);
	}
}
Code language: C# (cs)

複数のレコードの挿入

param にオブジェクトのリストを渡すとき 引数を指定すると、Dapper はリスト内のすべてのオブジェクトに対して SQL クエリを実行します:

private const string INSERT_SQL =
@"INSERT INTO [dbo].[Movies]
	([Name]
	,[YearOfRelease]
	,[Description]
	,[Director]
	,[BoxOfficeRevenue])	   
VALUES
	(@Name,
	@YearOfRelease,
	@Description,
	@Director,
	@BoxOfficeRevenue)";

public void InsertMultiple(List<Movie> movies)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute(INSERT_SQL, param: movies);
	}
}
Code language: C# (cs)

多くの INSERT ステートメントを順番に実行すると、パフォーマンスが大幅に低下する可能性があります。このような大量のデータを頻繁に挿入することが予想される場合は、必ずコードのパフォーマンス テストを行ってください。パフォーマンスの問題が発生した場合は、BULK INSERT を実行することを強くお勧めします。

記録の更新

Dapper を使用してレコードを更新する方法の例を次に示します。

public void UpdateYear(Movie movie)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute("UPDATE Movies SET YearOfRelease=@year WHERE Id=@id", 
			param: new {year = movie.YearOfRelease, id = movie.Id });
	}
}
Code language: C# (cs)

最小限の列のみをクエリに含めることで、UPDATE ステートメントをできるだけ単純に保つことができます。列を更新リストまたは where 句に含める必要がない場合は、省略してください。

複数のレコードの更新

複数のレコードを異なる値で更新する場合は、複数の UPDATE ステートメントを実行する必要があります。たとえば、次のように設定するとします:

  • 映画 A YearOfRelease=2021
  • 映画 B YearOfRelease=2022

Dapper でこれを行うには、param のリストを渡すことができます 口論。リスト内の各ムービー オブジェクトに対して UPDATE ステートメントを実行します。

public void UpdateMultipleToDifferentYears(List<Movie> movies)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute("UPDATE Movies SET YearOfRelease=@YearOfRelease WHERE Id=@Id",
			param: movies);
	}
}
Code language: C# (cs)

複数のレコードを同じ値で更新する場合は、WHERE IN 句を使用して単一の UPDATE ステートメントを実行できます。たとえば、YearOfRelease=2022 になるように複数の映画を更新するとします。

Dapper でこれを行う方法は次のとおりです。

using System.Linq;

public void UpdateMultipleWithSameYear(int year, List<Movie> movies)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute("UPDATE Movies SET YearOfRelease=@year WHERE Id IN @ids",
			param: new { year, ids = movies.Select(m => m.Id) });
	}
}
Code language: C# (cs)

これは、UPDATE ステートメントが 1 つしか必要ないときに複数の UPDATE ステートメントを実行するよりも効率的です。

レコードの削除

Dapper を使用すると、レコードを簡単に削除できます。

public void Delete(Movie movie)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute("DELETE FROM Movies WHERE Id=@id",
			param: new { id = movie.Id });
	}
}
Code language: C# (cs)

複数のレコードの削除

複数のレコードを削除する場合、WHERE IN 句を使用して単一の DELETE ステートメントを実行できます。これを Dapper で行う方法は次のとおりです。

using System.Linq;

public void DeleteMultiple(List<Movie> movies)
{
	using (var con = new SqlConnection(connectionString))
	{
		con.Execute("DELETE FROM Movies WHERE Id IN @ids",
			param: new { ids = movies.Select(m => m.Id) });
	}
}
Code language: C# (cs)

これは、複数の DELETE ステートメントを実行するよりも効率的です。


No