|
|
6 ~% J, R' B! m8 z. e
<h2 id="系列导航">系列导航</h2>
& C1 V" L8 H2 y9 y* u- k" ^8 m! Q<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
" y) B' G% h5 w6 R( W% _7 H* x" F<h2 id="需求">需求</h2>
/ |# M/ q- E- M1 [$ p; g<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
; Y7 Z `; L1 i% J. k" }<h2 id="思路">思路</h2>
# o) A; f! ~/ l8 b+ Q1 U- ?$ r1 k<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
3 z8 p/ o6 N7 R1 Y1 {: |$ h" n<h2 id="实现">实现</h2>
T5 U$ }- d5 c9 B<p>为了保持简单,我们先定义以下两个类型:</p>+ b0 l+ m C8 F2 l/ l
<pre><code class="language-c#">// 定义新增Post的参数 ?' C+ k: Q- u5 I3 f* D c- A
public record AddPostInput(string Title, string Author);
+ x5 a4 f( k( W! f* U/ A
! f+ e2 S1 S1 G+ {// 定义新增Post的返回对象
% I' y; ~6 e) j% q) bpublic record AddPostPayload(Post Post);
% u* `! S6 X0 M8 [ J3 K; D</code></pre>/ Z9 q1 ^+ a( _
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
) J- L) S& c( m) Y<ul>
_( w0 c5 X- |+ c: g<li><code>Mutation.cs</code></li>& k( B+ X7 f9 Y6 U7 \) j0 s
</ul>
# V9 W# X* o/ f% o5 |<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
9 L3 J1 _9 B# C `$ ~ I6 g: ]1 F% l- J) o( J( T9 K) V0 }# u
public class Mutation
5 Q3 ]% v' B5 i7 N7 b! \{5 u, ?2 e1 s6 B o6 `0 e
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)7 M% ]& t8 d" |) I9 m: m9 W. X& f
{
5 P8 v9 I; y7 O/ h0 I4 S1 C return new AddPostPayload(await repository.AddAsync(new Post
0 m3 ]* n( [3 V4 L9 i {, i0 C% O# \. b0 z/ p. l
Title = input.Title,& Q8 i8 b4 t) M7 p% }. H
Author = input.Author5 t2 u% o5 b9 h( I5 |1 V+ z
}));
3 S* J9 H- r7 x' A+ D$ Q }! q- `; [% R. B
}" U4 `: f {/ V. l6 f
1 G% }- W$ @4 f% z8 v
</code></pre>3 s( x N* N" ?. j
<p>最后在注入服务的地方进行配置:</p>/ D: N4 T% d0 ?
<ul>* S# m0 h9 |. v
<li><code>ProgramExtensions.cs</code></li>
7 z' Y/ ~( x' l2 ]1 i+ \- o</ul>6 i& m3 b& G5 P0 g1 ~+ L9 }
<pre><code class="language-c#">builder.Services
2 d. w; u$ v7 h6 R .AddGraphQLServer(). a4 Y( X( V, `8 V" M" z% o0 ^
.SetPagingOptions(new PagingOptions% K) M# H% R' L6 G( [6 B0 y
{
( B$ d8 q( n+ N MaxPageSize = 50,5 {( u# _1 j! p' u' \
IncludeTotalCount = true
5 p2 U u2 Z! }0 ?7 B% j8 A })
+ l, w- J, t" p( C/ x .AddFiltering()
+ R0 R: z- B" N" r3 E: }: s4 S .AddProjections()2 J' ?) Q; j6 w
.AddSorting()) J, G0 i& w* r$ x
.AddQueryType<Query>()
4 |4 K: {4 Z0 G% f. v .AddMutationType<Mutation>()! y5 R; X8 @- E2 i' A0 o* ~% {3 u
.AddMutationConventions(new MutationConventionOptions. v/ Z& w2 A' V; C; r' S5 G0 p
{
$ |. b1 j1 s; ?8 k, t ApplyToAllMutations = true,$ z& j( R8 ^+ y
InputArgumentName = "input",3 R" _# B0 B, f$ F* ?+ d
InputTypeNamePattern = "{MutationName}Input",
$ Z0 s. w1 y% d" c3 E. D7 I PayloadTypeNamePattern = "{MutationName}Payload",
0 r8 f- ^% @: k3 v8 L( `9 | PayloadErrorTypeNamePattern = "{MutationName}Error",$ f2 q$ O2 I9 ]& f
PayloadErrorsFieldName = "errors"( E; u( u3 f; G. e) F
})8 ^3 }, |* N2 G1 s4 [ u* m, b# D
.AddType<PostType>();
5 i9 I0 c( x0 S" L% W8 ]9 s</code></pre>9 F+ o, u4 k" E- d) N0 P- P
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>! j, o9 A. @+ g5 ~; N
<h2 id="验证">验证</h2>
4 Q8 R( i" _0 s$ R<p>启动<code>Api</code>项目,调用接口:</p>
( ?8 J8 S9 z$ j G) }<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>/ l- d% |8 Q% m: \
<p>终端的日志输出如下:</p>, W- Q$ E/ u! W2 T) E
<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']5 ^9 E5 |9 h7 f2 [7 D" a
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
2 [/ q/ E: B# s+ q H* [VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
1 C- J' p( q" C% j: I[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'; x7 _7 E8 B9 X4 y' o" o- n
</code></pre>
( n$ x$ @8 m% L) _8 b O<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>7 j' c. Y9 M- U) E
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>! f; K ]' t8 @ \" ~7 Q% b" {) _3 O# B: X
<h2 id="总结">总结</h2>
0 q1 W) C: O+ [; V% z8 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>4 P5 I1 t- Q& o
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>+ e& q/ |/ `, U
( c: Q ]: u' W
|
|