|
|
" s, t8 Q9 ^/ b$ }' @ H2 s& B7 _, T
<h2 id="系列导航">系列导航</h2>
" Q: T( ^! b8 m+ l6 K- ]<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
5 H" I% b+ g9 k9 ~, V& V<h2 id="需求">需求</h2>- @" ]7 E5 C2 g9 y, ?: k
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>4 P+ I( Y0 {/ ?# ?+ @" H l
<h2 id="思路">思路</h2>
) R- v1 }' \$ S, @$ ]0 S% }<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
% B: x' B6 A1 ]<h2 id="实现">实现</h2>
! A0 z/ S* m# G/ s/ Q" A) A+ @- A: r<p>为了保持简单,我们先定义以下两个类型:</p>
8 o; @$ ^6 T, j* m2 W' ]<pre><code class="language-c#">// 定义新增Post的参数! M0 Z) L$ v1 R7 }" y
public record AddPostInput(string Title, string Author);
# G" a4 {- a/ U2 z1 `# U a6 {" l: A# T t4 o3 Z
// 定义新增Post的返回对象- a$ [2 g( c X: x' Q' A
public record AddPostPayload(Post Post);
2 e# @" E% _4 f( d</code></pre>2 X2 H$ d2 n. R+ X! {7 W! X
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
! [7 m( ]* [# j, l4 n, d; d0 L# _<ul>
0 R z6 G3 O) J# Z# ]<li><code>Mutation.cs</code></li>
* C! r* v7 P( D2 {) x</ul>- l% g7 b5 J; r8 ^/ B$ N' [
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;+ d3 o6 u6 k$ _/ s; p: f
1 q3 V7 T( b/ ^8 K2 @8 y' ?; S5 Qpublic class Mutation
6 g3 b6 _7 |. M4 u' C% F{
) d8 N# d% h [6 ], S3 j public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
/ t& E6 q& T% u: |& e% n {
0 |, L8 P* H, `; g7 g, E4 p return new AddPostPayload(await repository.AddAsync(new Post
4 y) Q+ @4 g( N q. L/ r( \ {
" F: {6 u+ |1 h1 c) g. L3 \ Title = input.Title,0 F# [7 X4 `8 X8 M$ v
Author = input.Author
9 i- X8 S) E. j9 K: h }));
( v6 \2 E$ k' K }
$ d1 G/ N: s& S; K, _, H. F* M* z, K}$ }# `3 p6 o$ v
4 J+ b: Z9 y" J5 M4 F</code></pre>
( M- L+ }$ v E7 g<p>最后在注入服务的地方进行配置:</p>
2 x$ E! u" ~0 D1 l& J<ul>0 J L9 r3 A. r1 a8 W
<li><code>ProgramExtensions.cs</code></li>
9 x# G* `; e- T/ [</ul>* M2 F6 N& Y5 `1 v+ @
<pre><code class="language-c#">builder.Services
1 ]7 ^% n+ k4 K5 Y4 g8 E2 q .AddGraphQLServer()' G& V* Y Z, y# H z0 i% x+ e {
.SetPagingOptions(new PagingOptions
, h% g' l: X/ i1 l# L. E, F/ A {
2 g% L( Q! Y. V3 Z: b MaxPageSize = 50,* o: t0 T* i1 w' t0 z
IncludeTotalCount = true+ `# [. v0 r: |6 D
})# o4 [0 h6 ?5 p( |/ z) u8 T
.AddFiltering()
. I+ p' T; v! F! f3 ?* v- } .AddProjections()
* a( w* F4 r; N4 k. A .AddSorting() G6 a6 F0 s& y
.AddQueryType<Query>()+ D6 ?+ L7 I; `
.AddMutationType<Mutation>()' k, p, c& c" P( i: `
.AddMutationConventions(new MutationConventionOptions$ D- q. w9 Y$ R) X; k! y& f
{- z7 }5 [* \5 S; _
ApplyToAllMutations = true,+ F6 w* s9 g$ x
InputArgumentName = "input",. L% d' v9 ]( u- ^
InputTypeNamePattern = "{MutationName}Input",
& W* ?0 V, ?0 c' n( B6 b" V PayloadTypeNamePattern = "{MutationName}Payload",
, [- `, i% _/ u- _ PayloadErrorTypeNamePattern = "{MutationName}Error",
1 k% r0 \5 L5 q( k+ f PayloadErrorsFieldName = "errors", a5 M" m6 X: Q4 F9 ?2 Z* _% c
})9 w( E3 A, l! g1 S |
.AddType<PostType>();: e6 K! t) x, V4 j9 D/ y
</code></pre>- q7 a& U8 ?7 d
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p># b# a$ M! B/ u9 s
<h2 id="验证">验证</h2>
5 w W- O( @, ?2 C9 M8 Z# L<p>启动<code>Api</code>项目,调用接口:</p>4 R( b' v! ^" c
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
* h: l4 w' p* N) _% m4 h6 Z/ e3 X& c<p>终端的日志输出如下:</p>
/ A( G ^0 m$ Y: S s3 g9 }; L<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']* j/ q/ }2 F- `! S% e' u L3 R
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")* L! O( F2 Y2 O% l( h0 Y
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);- T/ C; [( {* o' w) \) `' b
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
, J+ F2 r/ j! x, x</code></pre>
5 m' s# |6 b& K9 \: p5 j<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>, D2 \3 W* ^( N9 n0 {7 ?) X% o
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>. t! z( w5 q& u9 E1 g
<h2 id="总结">总结</h2>
# {; F" N `( K T. U; W<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>. C3 n0 @% ~" G$ b1 I
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>! m* m2 R9 F! l4 R9 A5 v
) C, k& F2 _* l) e |
|