• 使用Hot Chocolate和.NET 6构建GraphQL应用(9) —— 实现Mutate更新数据


    系列导航#

    使用Hot Chocolate和.NET 6构建GraphQL应用文章索引

    需求#

    在上一篇文章中,我们演示了如何使用Hot Chocolate进行GraphQL的Mutate新增数据,这篇文章我们将演示如何实现GraphQL中的数据更新任务。

    思路#

    对数据的更新和新增数据的思路是一样的,都是使用Mutate机制进行更新。

    实现#

    为了保持简单,我们先定义以下两个类型:

    // 定义更新Post的参数
    public record UpdatePostInput(Guid Id, string Title, string Author);
    
    // 定义新增Post的返回对象
    public record UpdatePostPayload(Post Post);
    

    新建Mutation.cs用来定义相关接口:

    • Mutation.cs
    public async Task<UpdatePostPayload> UpdatePostAsync(UpdatePostInput input, [Service] IRepository<Post> repository)
    {
        var post = await repository.GetSingleAsync(p => p.Id == input.Id);
        if (post == null)
        {
            throw new ArgumentException($"no post with id: {input.Id} can be found!");
        }
    
        post.Title = input.Title;
        post.Author = input.Author;
    
        return new UpdatePostPayload(await repository.UpdateAsync(post));
    }
    

    这样就实现了更新Post的需求,下面我们来验证一下。

    验证#

    启动Api项目,先查询所有的Post数据:

    img

    接下来对其中一条Post进行更新:

    img

    终端的日志输出如下:

    [15:44:17 INF] Executing endpoint 'Hot Chocolate GraphQL Pipeline'
    [15:44:17 INF] Executed DbCommand (0ms) [Parameters=[@__input_Id_0='?' (DbType = Guid)], CommandType='Text', CommandTimeout='30']
    SELECT "p"."Id", "p"."Abstraction", "p"."Author", "p"."Content", "p"."Created", "p"."CreatedBy", "p"."LastModified", "p"."LastModifiedBy", "p"."Link", "p"."PublishedAt", "p"."Title"
    FROM "Posts" AS "p"
    WHERE "p"."Id" = @__input_Id_0
    LIMIT 1
    [15:44:17 INF] Executed DbCommand (0ms) [Parameters=[@p10='?' (DbType = Guid), @p0='?' (Size = 66), @p1='?' (Size = 22), @p2='?' (Size = 30), @p3='?' (DbType = DateTime), @p4='?', @p5='?' (DbType = DateTime), @p6='?', @p7='?' (Size = 26), @p8='?' (DbType = DateTime), @p9='?' (Size = 59)], CommandType='Text', CommandTimeout='30']
    UPDATE "Posts" SET "Abstraction" = @p0, "Author" = @p1, "Content" = @p2, "Created" = @p3, "CreatedBy" = @p4, "LastModified" = @p5, "LastModifiedBy" = @p6, "Link" = @p7, "PublishedAt" = @p8, "Title" = @p9
    WHERE "Id" = @p10;
    SELECT changes();
    [15:44:17 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
    [15:44:17 INF] Request finished HTTP/1.1 POST https://localhost:7194/graphql application/json 288 - 200 - application/json;+charset=utf-8 8.6091ms
    

    再进行一次查询:

    img

    可以看到更新后的Post已经存储到数据库中了。

    如果我们使用错误的Id去尝试更新数据,那么会得到这样的返回:

    img

    但是这样我们并不能看到具体的错误信息,即使我们在代码中已经明确throw了异常并填入了错误信息。接下来我们来解决这个问题。

    扩展:自定义异常返回#

    为了让GraphQL的schema能够识别异常类型,最简单的方式是通过属性[Error(typeof())]来指定异常类型,我们当然可以穿入ArgumentException异常类型,为了演示如何自定义异常类型。我们新建一个异常类:

    namespace PostGraphi.Api.GraphQL.Exceptions;
    
    public class PostNotFoundException : Exception
    {
        public PostNotFoundException(Guid id)
            : base($"no post with id: {id} can be found!")
        {
        }
    }
    

    并修改Mutate方法属性和抛出异常的代码:

    [Error(typeof(PostNotFoundException))]
    public async Task<UpdatePostPayload> UpdatePostAsync(UpdatePostInput input, [Service] IRepository<Post> repository)
    {
        var post = await repository.GetSingleAsync(p => p.Id == input.Id);
        if (post == null)
        {
            throw new PostNotFoundException(input.Id);
        }
        post.Title = input.Title;
        post.Author = input.Author;
        return new UpdatePostPayload(await repository.UpdateAsync(post));
    }
    

    最后还需要在引入依赖的时候进行配置,选择返回结果中包含具体的错误信息:

    builder.Services
        .AddGraphQLServer()
        // .....
        .ModifyRequestOptions(opt => opt.IncludeExceptionDetails = true);
    

    再来测试一下:

    img

    在extension中我们看到了自定义的错误信息输出。

    总结#

    在本文中我们实现了简单的更新Post操作,对于删除数据来说,思路并没有区别,所以我们下一篇文章将会直接介绍GraphQL中的另一大特性:Subscription。

  • 相关阅读:
    ky10 server x86 安装、更新openssl3.1.4(在线编译安装、离线安装)
    【Edabit 算法 ★☆☆☆☆☆】Power Calculator
    放大镜-第12届蓝桥杯Scratch选拔赛真题精选
    云服务器与内网穿透有什么区别?哪个好用?
    C# 第三章:类、接口与结构 学习笔记
    查找算法【哈希表】 - 处理冲突的方法:开放地址法-二次探测法 & 随机探测法 & 再散列法
    电容传感器
    Angular RouterModule.forRoot(ROUTES) 和 forChild(ROUTES)的区别
    助力大厂offer,这份Java面试最全八股文不可错过
    使用Dom4j解析XML
  • 原文地址:https://www.cnblogs.com/code4nothing/p/graphql-net6-9.html