MiniAPI(二十五)：Dapper

注：すでにDapperを使用している方は、この記事をスキップしても構いません。
第十二回で、公式のORMであるEntityFrameworkについて話しました。これはSQLの詳細を隠蔽してくれるため、いくつかの標準化されたリレーショナルデータベースプロジェクトにとって非常に便利です。今日は、別の人気のあるORMであるDapperについて紹介します。DapperはIDbConnectionのメソッドを拡張することで、データ処理を実現します。その特徴は柔軟さと高効率です。
プロジェクトを通じてDapperの使用方法を見てみましょう。まず、2つのNuGetパッケージをインストールします。引き続き、以前のExamプロジェクトのテーブルを使用してDapperの使用方法を説明します。データベースはSQL Serverです。
DapperとSqlClientをインストール：
```
Install-Package Dapper
Install-Package Microsoft.Data.SqlClient
```
以下はQuestionに対するCRUD操作です：
```csharp
using Dapper;
using Microsoft.Data.SqlClient;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IQuestionService, QuestionService>();

var app = builder.Build();

app.MapPost("/question", async (IQuestionService questionService, QuestionModel question) => {
    return await questionService.AddQuestionAsync(question);
});

app.MapPut("/question", async (IQuestionService questionService, QuestionModel question) => {
    return await questionService.ModifyQuestionAsync(question);
});

app.MapGet("/question/{id}", async (IQuestionService questionService, int id) => {
    return await questionService.GetQuestionAsync(id);
});

app.MapDelete("/question/{id}", async (IQuestionService questionService, int id) => {
    return await questionService.DeleteQuestionAsync(id);
});

app.Run();

public interface IQuestionService {
    Task<QuestionModel> GetQuestionAsync(int id);
    Task<bool> AddQuestionAsync(QuestionModel question);
    Task<bool> DeleteQuestionAsync(int id);
    Task<bool> ModifyQuestionAsync(QuestionModel question);
}

public class QuestionService : IQuestionService {
    private readonly SqlConnection _connection;

    public QuestionService(IConfiguration configuration) {
        var connectionString = configuration.GetConnectionString("ExamDatabase");
        _connection = new SqlConnection(connectionString);
    }

    public async Task<bool> AddQuestionAsync(QuestionModel question) {
        var sql = @"INSERT INTO [Questions]
                  ([Question]
                  ,[Score]
                  ,[QuestionTypeID]
                  ,[SujectTypeID])
             VALUES
                  (@Question
                  ,@Score
                  ,@QuestionTypeID
                  ,@SujectTypeID)";
        return (await _connection.ExecuteAsync(sql, question)) > 0;
    }

    public async Task<bool> DeleteQuestionAsync(int id) {
        var sql = @"delete from questions where id=@id";
        return (await _connection.ExecuteAsync(sql, new { id })) > 0;
    }

    public async Task<QuestionModel> GetQuestionAsync(int id) {
        var sql = @"select * from questions where id=@id";
        return await _connection.QuerySingleAsync<QuestionModel>(sql, new { id });
    }

    public async Task<bool> ModifyQuestionAsync(QuestionModel question) {
        var sql = @"UPDATE [dbo].[Questions]
   SET [Question] = @Question
      ,[Score] = @Score
      ,[QuestionTypeID] = @QuestionTypeID
      ,[SujectTypeID] = @SujectTypeID
 WHERE ID=@ID";
        return (await _connection.ExecuteAsync(sql, question)) > 0;
    }
}
```

上記の例から、DapperはIDbConnectionの拡張メソッドを通じて機能を提供していることがわかります。基本的に、クエリには`Query<T>(sql,Param,...)`を、追加・削除・更新には`Execute(sql,T,...)`を使用します。Dapperの便利な点は、Tがすべて自動的にSQL内のパラメータにマッピングされるため、SQLを柔軟かつ高効率な構文で書くことができ、パラメータをSQLに簡単に組み込むことができるという点です。以下の図を参照：

![alt 画像](https://mmbiz.qpic.cn/mmbiz_png/4CAA63nvHRDB2kI8XP0qdiaO5g7WxXrrpTjkEwvHOrqkwlzhQSeVWBuAiaH3yr4P2s7hjWibicQe24BGBibTibvYrFcA/640?wx_fmt=png)

Dapperのより豊富な使用方法については、Githubのリポジトリのドキュメントをご覧ください：https://github.com/DapperLib/Dapper

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247485001&idx=1&sn=ae3fb9d53063e0bd17e86e24ab2fb897&chksm=9f005963a877d075d5fdf0015def1d589365a65c473efff33e708258d7912412fb4da25e155d&token=347102560&lang=zh_CN#rd