|
|
: ?& [. v- m) c8 w4 @% |& c0 ~<h2 id="系列导航">系列导航</h2>
0 b& L# |5 O7 W, L<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>5 F( y' ]4 y F% D6 c
<h2 id="需求">需求</h2>
! `: C5 G$ R. N8 n6 z( |' o4 o<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
% x7 B' n; j2 S( `& w<h2 id="思路">思路</h2>
. b: r/ I; H$ p' J, Q3 d! G<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
, d3 {. g C% ]( A% Z+ r<h2 id="实现">实现</h2>
' Y: x; P2 ^% Y& S% {9 Q5 a<p>为了保持简单,我们先定义以下两个类型:</p>1 e3 J: ~5 z x y* M2 t
<pre><code class="language-c#">// 定义新增Post的参数
. _' y( U0 h X) Y# Kpublic record AddPostInput(string Title, string Author);8 k0 ]2 ?7 K0 @8 t; J
5 t7 V e1 ~ G1 {
// 定义新增Post的返回对象7 M% N$ {: C4 n+ c L) _
public record AddPostPayload(Post Post);( N& h E/ F6 [6 s% j/ [
</code></pre>' {& f8 x6 B3 A5 j5 f
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>6 }. n; a% g3 O* _
<ul>1 z$ g3 Y9 }0 }# T+ Q
<li><code>Mutation.cs</code></li>
+ m6 z* z/ y" v) @0 \ t</ul>
5 f( o% e! @) w4 z ~& }, x<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;( @& |3 D3 @. O2 M3 z B0 B
. m2 }/ t' b, {
public class Mutation+ Q7 A4 D+ ]1 j4 c5 K0 w
{
/ y/ @ d3 e1 N2 ^% k public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
& ]2 x" a$ X t) g& b {
* s, Y8 E$ W5 _( E# n* [! M return new AddPostPayload(await repository.AddAsync(new Post# Q/ g& B6 b# \( |* G* o( l8 ]
{4 M; F& H$ a/ z2 [
Title = input.Title,) _4 e% C5 W/ B5 m. P+ k
Author = input.Author
c' G/ C0 B( U+ ]7 S2 M }));
* p6 {) }/ \; j2 ?: U7 T }
0 ^3 q% G d& f0 `+ o( T: Z& `}
/ X8 |+ d" z7 n- T- z% {
' L8 I: c5 ]% H. y" u</code></pre>
' e; N9 c k7 }: _$ l4 g- ^3 ~; }8 U. D, B<p>最后在注入服务的地方进行配置:</p>
/ q/ s4 T& u) W# h3 m/ ]" x<ul>; G+ z( m6 R8 G7 V
<li><code>ProgramExtensions.cs</code></li>
: M3 ? q8 H9 N" I. m</ul># K i; n3 I1 g3 j% A4 {. i# ~
<pre><code class="language-c#">builder.Services
2 u0 @- E" `0 O4 `+ Z% ~9 W .AddGraphQLServer()/ o# l8 r$ x5 p N9 J
.SetPagingOptions(new PagingOptions
9 D' d) ^7 x: a/ T {4 E, M6 t' P6 C
MaxPageSize = 50," \. X. t# n B/ W3 w
IncludeTotalCount = true
g# j, _" O: u })
7 |- @9 V; O0 Y .AddFiltering()
+ H+ t: F* e2 J/ h9 [9 \ .AddProjections()
z' s. t0 y9 K" w2 n" e5 u .AddSorting()! C/ h- E/ X: T' J0 {. M2 @
.AddQueryType<Query>()
: k- i6 V! S6 i4 X; a( J, K .AddMutationType<Mutation>()
* @2 k" \9 j/ X9 ~! F .AddMutationConventions(new MutationConventionOptions
4 e5 O M3 d( ] B6 e% X4 n) H {: |4 I5 u9 t& }3 s% k2 P& n
ApplyToAllMutations = true,
0 v( N; t c( i InputArgumentName = "input",
1 g8 M: M1 e7 l- Y InputTypeNamePattern = "{MutationName}Input", J# n& |- Q3 o' D
PayloadTypeNamePattern = "{MutationName}Payload",
% r, ~9 Z4 |: O4 g PayloadErrorTypeNamePattern = "{MutationName}Error",' p2 C0 k2 y' D3 N
PayloadErrorsFieldName = "errors"
* [ |8 H0 E1 ^$ @" N% e5 c })
( U0 d( n/ T6 s& a2 S .AddType<PostType>();
/ Y4 x$ F9 _+ f1 q</code></pre>
0 T4 z, S# B, U* h1 K( `( S: J- r<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
. w# M8 M+ @4 K) ^5 m" ?<h2 id="验证">验证</h2>4 H! ?: w# c; y3 c
<p>启动<code>Api</code>项目,调用接口:</p>% }! h f; x$ g
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>1 N$ B& s7 S' i2 { L
<p>终端的日志输出如下:</p>
+ o4 N* d) C9 _" O- V<pre><code class="language-bash">[10:45:15 INF] Executed DbCommand (1ms) [Parameters=[@p0='?' (DbType = Guid), @p1='?', @p2='?' (Size = 13), @p3='?', @p4='?' (DbType = DateTime), @p5='?', @p6='?' (DbType = DateTime), @p7='?', @p8='?', @p9='?' (DbType = DateTime), @p10='?' (Size = 30)], CommandType='Text', CommandTimeout='30']! C! H0 o7 q+ [+ B& ^+ Z0 t
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")) t7 j: L* t- n6 q
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
% g3 J) {8 I/ j7 a[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
; s3 D+ J4 X& A4 R</code></pre>$ a/ c1 r3 P3 U& f
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>1 F' n$ @$ L, `: K2 g
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>3 v/ `6 S/ r5 s5 ^5 v
<h2 id="总结">总结</h2>
, c" Q% J+ H W* J& M" f0 J2 W9 T<p>在本文中我们实现了简单的新增Post操作,这里还有一些涉及到错误处理的内容,我没有在文章中演示,可以参考官方文档 <a href="https://chillicream.com/docs/hotchocolate/defining-a-schema/mutations/#errors">Errors</a>,在自定义异常对象后,有三种方式可以进行错误处理:直接返回异常;使用异常工厂方法;使用构造函数。甚至可以在<code>AggregateExceptions</code>中一次性返回多个异常。基本思路都是通过添加属性<code>[Error(typeof(SomeUserDefinedException))]</code>来实现的。</p>
6 N* i) a& i# ]: [* N" O9 F( h<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>
' D! z2 b# S7 b! m
4 h4 z5 n9 l" U |
|