C#でGraphQLその２（やるなホットチョコレート）


引き続き、[ホットチョコレート](https://chillicream.com/docs/hotchocolate/v13)を調査したいと思います。
今回はフィルタリングとページネーションを調査したいと思います。

前回の記事はこちら
[C#でGraphQL（なぜホットチョコレート？！）](https://qiita.com/htagu/items/ab1579c501ae5559b05b)

# 簡単でした！
結論としてはNugetでのモジュール追加とQueryクラスの関数にアトリビュートを追加するだけでした。
* フィルタリングも１通りの機能が揃っていてカスタマイズもできるようです。
* ページネーションは「Cursor Connections」という仕様のようです。

手順は以下です。
1. Nugetで"HotChocolate.Data"を追加してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666176/5f68a928-984e-b3f1-6e5d-6b354de48be2.png)

2. [UsePaging]と[UseFiltering]アトリビュートを追加してください。
    ```C#
    public class Query
    {
        [UsePaging]
        [UseFiltering]
        public IEnumerable<Author> Authors([Service] Repository repository) =>
            repository.GetAuthors();
        [UsePaging]
        [UseFiltering]
        public IEnumerable<Book> Books([Service] Repository repository) =>
            repository.GetBooks();
    }
    ```
# テスト
フィルタリング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666176/ef47f348-19cf-130e-2d73-18682e81a18c.png)

ページネーション1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666176/41c9bb27-50e7-de57-0747-dbaf80545d44.png)

ページネーション2 （afterにendCursorを設定すると次の1件取得）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666176/ac5edb6b-c0c1-cc06-0c2a-885451f949fd.png)



# 感想
なんかHotChocolateよくできてますね。
次は本丸のEFCoreでSQLServerに接続してみたいと思います。
N+1とかどうなっているんでしょうか

# コード
一応コードも載せておきますので、試したい場合はProgram.csを置き換えてください。
とはいっても４行くらい追加しただけだけど。。。
```C#
var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddSingleton<Repository>()
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddFiltering()
    .AddType<Author>()
    .AddType<Book>();
var app = builder.Build();

app.MapGraphQL();

app.Run();

public class Query
{
    [UsePaging]
    [UseFiltering]
    public IEnumerable<Author> Authors([Service] Repository repository) =>
        repository.GetAuthors();
    [UsePaging]
    [UseFiltering]
    public IEnumerable<Book> Books([Service] Repository repository) =>
        repository.GetBooks();
}

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    [UsePaging]
    [UseFiltering]
    public List<Book> Books { get; set; }
}
[UsePaging]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
}
public class Repository
{
    private readonly List<Author> _authors;
    public Repository()
    {
        //データ登録
        _authors = new List<Author>();

        //川端康成
        var auther = new Author
        {
            Id = 1, Name = "川端康成",
        };
        auther.Books = new List<Book>
        {
            new Book { Id = 11, Title = "雪国", Author = auther},
            new Book { Id = 12, Title = "伊豆の踊り子", Author = auther}
        };
        _authors.Add(auther);

        //夏目漱石
        auther = new Author
        {
            Id = 2, Name = "夏目漱石",
        };
        auther.Books = new List<Book>
        {
            new Book { Id = 21, Title = "坊ちゃん", Author = auther},
            new Book { Id = 22, Title = "三四郎", Author = auther}
        };
        _authors.Add(auther);
    }
    public IEnumerable<Author> GetAuthors()
    {
        return _authors;
    }
    public IEnumerable<Book> GetBooks()
    {
        return _authors.SelectMany(x => x.Books);
    }
}

```