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

  • A+
所属分类:.NET技术
摘要

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


系列导航

使用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数据:

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

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

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

终端的日志输出如下:

[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 

再进行一次查询:

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

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

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

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

但是这样我们并不能看到具体的错误信息,即使我们在代码中已经明确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); 

再来测试一下:

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

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

总结

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