【C#】高速ORM「LtQuery」の書き込み処理

LtQueryが書き込み処理(INSERT/UPDATE/DELETE)に対応したので使い方を紹介致します。

#### 関連記事
- [【C#】LtQueryがDapper・EFCoreを超したかも知れない](https://qiita.com/maikami03/items/5b95b41a990e6272f17b)

## 概要
LtQuery(リトルクエリ)はEF Coreのように**LINQやInclude()でSQLを構築**する機能が備わっていてかつ、**パフォーマンスがDapperを凌いでいる**といういいとこ取りの高速O/Rマッパー(ORM)です。

### SELECT
| ORM  | Mean     | Error     | StdDev    | Gen0     | Gen1     | Allocated |
|-------- |---------:|----------:|----------:|---------:|---------:|----------:|
| ADO.NET | 3.883 ms | 0.0633 ms | 0.0592 ms | 296.8750 | 203.1250 |   1.44 MB |
| **LtQuery** | **3.906 ms** | **0.0380 ms** | **0.0337 ms** | **296.8750** | **195.3125** |   **1.44 MB** |
| Dapper  | 4.416 ms | 0.0255 ms | 0.0226 ms | 359.3750 | 187.5000 |   1.62 MB |
| EFCore  | 6.816 ms | 0.0720 ms | 0.0673 ms | 554.6875 | 367.1875 |    2.6 MB |

### INSERT

| ORM     | Mean     | Error    | StdDev   | Gen0    | Allocated |
|-------- |---------:|---------:|---------:|--------:|----------:|
| ADO.NET | 392.9 μs |  7.67 μs |  9.13 μs |  6.3477 |  13.46 KB |
| **LtQuery** | **359.7 μs** |  **6.87 μs** |  **8.44 μs** |  **6.3477** |  **13.74 KB** |
| Dapper  | 395.9 μs |  7.85 μs | 13.33 μs |  9.7656 |   20.4 KB |
| EFCore  | 983.0 μs | 19.65 μs | 35.43 μs | 78.1250 | 161.88 KB |

## 書き込み処理例

```csharp
class BlogService
{
    readonly ILtConnection _connection;
    public BlogService(ILtConnection connection)
    {
        _connection = connection;
    }

    // UnitOfWorkを使用しないパターン
    public void AddBlog(Blog blog)
    {
        _connection.Add(blog); // 即時実行される
    }

    // UnitOfWorkを使用するパターン
    public void AddBlog2(Blog blog)
    {
        using (var unitOfWork = _connection.CreateUnitOfWork())
        {
            unitOfWork.Add(blog);

            unitOfWork.Commit();  // まとめて実行される
        }
    }
}
```

`_connection.Add()` を使用した場合はクエリを即発行します。こちらはトランザクションを自身で管理したい場合に使います。`unitOfWork.Add()` は標準の書き込み方です。`Commit()` 時に蓄積したクエリをまとめて発行します。EF Core 同様 `Add()` されたエンティティはIDが付与されます。ただしEF Coreのようなトレース機能はありません。

```csharp
class BlogApplicationService
{
    readonly ILtUnitOfWork _unitOfWork;
    public BlogApplicationService(ILtUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
```

`ILtUnitOfWork` はDIコンテナにScopedで登録されています。`ILtUnitOfWork` は `ILtConnection` と同様Select/Single/Firstのメソッドを持っているためわざわざ `ILtConnection` と使い分ける必要もなく、上記コードのようなEF Core の `DbContext` に近い使い方もできます。

## もっと詳細な書き込み処理例

```csharp
class BlogRepository
{
    readonly ILtUnitOfWork _unitOfWork;
    public BlogRepository(ILtUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    // 1件追加
    public void Add(Blog blog)
    {
        _unitOfWork.Add(blog);
    }
    // 複数追加
    public void AddRange(IEnumerable<Blog> blogs)
    {
        _unitOfWork.AddRange(blogs);
    }
    
    // 1件更新
    public void Update(Blog blog)
    {
        _unitOfWork.Update(blog);
    }
    // 複数更新
    public void UpdateRange(IEnumerable<Blog> blogs)
    {
        _unitOfWork.UpdateRange(blogs);
    }
    
    // 1件削除
    public void Remove(Blog blog)
    {
        _unitOfWork.Remove(blog);
    }
    // 複数削除
    public void RemoveRange(IEnumerable<Blog> blogs)
    {
        _unitOfWork.RemoveRange(blogs);
    }
}
```

## 後書き
今回も自己布教でした。すいません。